在下面的示例中,函数模板(quartic
)使用重载的全局函数(square
)。编译时,仅考虑在模板本身之前声明的重载,因此即使使用模板之前声明了square(int)
,也使用square(double)
而不是square(double)
。
int square(int);
template<typename T>
T quartic(T value) {
return square(square(value));
}
double square(double);
double x(double y) {
return quartic(4.0); // Uses square(int), wanted square(double)
}
有没有一种方法可以使square
的哪个重载版本的分辨率取决于使用模板时可用的内容,以便用户可以为任何类型square
实现T
}他使用了吗?
注意:奇怪的是,MSVC将使用square(double)
,而GCC,clang和icc使用square(int)
。
答案 0 :(得分:4)
函数模板square
中的quartic
是 依赖名称 ,这意味着它取决于模板参数T
和其查找被推迟到知道T
为止。此外,它是一个 不合格名称 (一个合格名称看起来像std::cout
),这意味着它不仅可以在其名称空间,但参数的名称空间,称为 依赖于参数的查找 , ADL < / em>。
在这种情况下:
很明显,不允许通过非ADL查找让示例工作。而且 ADL 也不这样做,因为 ADL 没有考虑double
。
,但是如果参数是用户定义的类型,则它由 ADL 使用。更清楚地讲,如果要调用在此作用域后定义的函数,则可以使该函数 通过ADL可见 ,这表示该函数和参数的类型(或间接类型,请参见[2])在同一名称空间中。
参考:
答案 1 :(得分:1)
仅应考虑在quartic
之前声明的函数,因此MSVC做错了。解决此问题的一种可能方法是也使square
成为功能模板,并让用户为其提供专门化功能。
您的代码:
template<typename T> T square(T);
template<typename T>
T quartic(T value) {
return square(square(value));
}
用户代码:
template<> int square(int value) {
return value * value;
}
template<> double square(double value) {
return value * value;
}