考虑以下代码:
#include <iostream>
#include <type_traits>
template <typename T>
class A
{
public:
// Allow func to be called if T is the const version of T2
// e.g., T is 'int const' and T2 is 'int'
template <typename T2,
typename = typename std::enable_if<
std::is_same<T, T2 const>::value>::type>
void func(A<T2> const &)
{
std::cout << "Conversion" << std::endl;
}
// Allow func to be called for same version of T
void func(A const &)
{
std::cout << "No conversion" << std::endl;
}
};
int main()
{
A<int const> a;
a.func(A<int const>{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
此代码在使用 GCC-8.3 编译时会编译并生成输出No conversion- 它选择了func不使用std::enable_if. 但是,如果我注释掉 的第二个版本func,它仍然会编译并现在生成输出Conversion。换句话说,这两个版本func中A是执行这种方法可用。鉴于两个重载都是可行的,编译器使用什么特定规则来选择func(A const &)另一个版本 ( func(A<T2> const &))?
规则是,如果非函数模板和函数模板特化具有相同的签名,则选择非函数模板而不是模板特化。这可以在[over.match.best]/2 中找到
鉴于这些定义,如果对于所有参数 i,ICSi(F1) 不是比 ICSi(F2) 更差的转换序列,那么一个可行函数 F1 被定义为比另一个可行函数 F2 更好的函数,然后
[...]
- F1 不是函数模板特化,F2 是函数模板特化 [...]