#include <iostream>
// maximum of two values of any type:
template<typename T>
T max (T a, T b)
{
std::cout << "max<T>() \n";
return b < a ? a : b;
}
// maximum of three values of any type:
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c); // uses the template version even for ints
} //because the following declaration comes
// too late:
// maximum of two int values:
int max (int a, int b)
{
std::cout << "max(int,int) \n";
return b < a ? a : b;
}
int main()
{
::max(47,11,33); // OOPS: uses max<T>() instead of max(int,int)
}
在这个例子中(从下面提到的书中)我不明白为什么:: max(47,11,33)调用期望使用max(int,int)。所以一个是2个参数,另一个是3个参数我认为它应该使用3个参数函数定义。
我错过了什么吗?
注:David Vandevoorde,Nicolai M. Josuttis,Douglas Gregor C ++模板:完整指南[第2版]书
答案 0 :(得分:6)
正在引发的问题是不会调用非模板重载。
max<T>(T a, T b, T c)
知道max<T>(T a, T b)
,但不知道有一个整数重载,因为它是在它之后声明的。
答案 1 :(得分:2)
解决方案是:为max<T>
专门设置T = int
,而不是定义int(int, int)
函数:
#include <iostream>
template<typename T>
T max (T a, T b)
{
std::cout << "max<T>() \n";
return b < a ? a : b;
}
template<>
int max (int a, int b)
{
std::cout << "max(int,int) \n";
return b < a ? a : b;
}
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c);
}
int main()
{
::max(47,11,33); // BINGO: uses specialized max<int>()
}
输出:
max(int,int)
max(int,int)
这很脆弱,如果在max<int>
定义max<T>
之后max<int>
使用max<T>
,T = int
已经专门化,根据[temp.expl.spec]/6
程序将是不正确的,无需诊断。
如果这是您无法承担的风险,您可以使用工具。 SFINAE就是其中之一,并且可以禁止使用<undefined />
来调用// Valid: Matrix of String tensors.
// Each element might have a different length.
byte[][][] matrix = new byte[2][2][];
matrix[0][0] = "this".getBytes("UTF-8");
matrix[0][1] = "is".getBytes("UTF-8");
matrix[1][0] = "a".getBytes("UTF-8");
matrix[1][1] = "matrix".getBytes("UTF-8");
Tensor<String> m = Tensor.create(matrix, String.class);
。这将导致工作程序或编译错误。
答案 2 :(得分:1)
::max(47, 11, 33);
实际上是::max<int>(47, 11, 33);
反过来会调用::max<int>(::max<int>(47, 11), 33);
这可能会令人惊讶。
由于int
是内置的(因此没有ADL),max(int, int)
应该在定义max(T, T, T)
之前可见,以允许在模板中调用该版本:
使用自定义类型,感谢ADL,您的max
函数可以在:
template <typename T>
T max (T a, T b)
{
std::cout << "max<T>()\n";
return b < a ? a : b;
}
// Should be declared **before** max(T, T, T)
int max(int a, int b)
{
std::cout << "max(int,int) \n";
return b < a ? a : b;
}
template<typename T>
T max (T a, T b, T c)
{
return max (max(a,b), c);
}
struct S {};
// Might be declared after max(T, T, T)
S max(S, S)
{
std::cout << "max(S, S)\n";
return {};
}
现在,max(0, 1, 2)
和max(s, s, s)
都会在内部调用非模板重载。