非类型函数模板参数

Non-type function template parameters

本文关键字:参数 函数模板 类型      更新时间:2023-10-16

我正在阅读c++模板完整指南,遇到了这个非类型函数模板参数代码(我添加了main()和其他部分,除了函数定义和调用):

#include <vector>
#include <algorithm>
#include <iostream>
template <typename T, int value>
T add (T const & element){
  return element + value;
}
int main() {
  int a[] = {1,2,3,4};
  int length = sizeof (a) / sizeof (*a);
  int b[length];
  std::transform (a, a + length, b, (int(*)(int const &))add <int, 5>); //why?
  std::for_each (b, b + length, [](int const & value){ std::cout << value << 'n'; });
  return 0; 
}

我读了这本书后不明白为什么我们需要函数调用的类型转换?

编辑:书中的解释:

add是一个函数模板,函数模板被认为是命名一组重载函数(即使该集合只有一个成员)。但是,根据现行标准,不能使用重载函数集进行模板参数推导。因此,必须转换为函数模板实参的确切类型:…

编译器:g++ 4.5.1在Ubuntu 10.10

严格地说,不能通过简单地给出模板参数列表来引用函数模板的专门化。你总是需要有一个目标类型(比如,你传递给的函数参数类型,或者你强制转换的类型,或者你赋值的变量类型)。

即使目标类型完全没有模板参数也是如此,例如

template<typename T> void f() { }
template<typename T> void g(T) { }
int main() {
  g(f<int>); // not strictly valid in C++03
  g((void(*)())f<int>); // valid in C++03
}

委员会增加了一些规则,这些规则被c++ 0x和流行的编译器在它们的c++ 03模式中采用,如果你提供了一个完整的模板实参列表,为所有模板形参提供类型,以及所有默认模板实参,则可以省略目标类型。