当模板参数类型相同时,我试图专门化两个模板参数的功能。我这样做的方式如下:
#include <iostream>
#include <type_traits>
using namespace std;
template<typename U, typename T>
int fun( U& u, T t );
template<>
inline
int fun( int& u, float t )
{
cout << "int, float" << endl;
return 0;
}
template<typename U, typename T>
inline
int fun( U& u, typename std::enable_if<std::is_same<U, T>::value ,T>::type t )
{
cout << "U == T" << endl;
return 0;
}
int main()
{
int a;
float b1, b2;
fun(a, b1);
fun(b1, b2);
return 0;
}
此代码编译良好(GCC 4.8.2)但链接器在fun
和U
相同类型时为所有T
调用提供未定义的引用。为什么它不起作用?
链接器输出:
g++ -std=c++11 test.cpp
/tmp/cc7HWboz.o: In function `main':
test.cpp:(.text+0x66): undefined reference to `int fun<float, float>(float&, float)'
collect2: error: ld returned 1 exit status
答案 0 :(得分:5)
问题
正在使用fun
来保护两种不同类型的实例的std::enable_if
有一个主要问题;它不能隐式推断类型T
。
这意味着当您使用fun
和b1
作为参数调用b2
时,您正在实例化template<typename U, typename T> int fun( U& u, T t )
,它没有定义..因此链接器错误。
解决方案
下面的代码有很多替代方案,但我认为这可能会让人感到困惑。
template<
typename U,
typename T,
typename = typename std::enable_if<std::is_same<U, T>::value>::type
>
inline int fun( U& u, T t)
{
cout << "U == T" << endl;
return 0;
}
inline int fun( int& u, float t )
{
cout << "int, float" << endl;
return 0;
}
在上面,编译器可以在我们的模板中推导T
和U
,也不需要所述模板的显式特化;我们可以使用C ++的重载规则,并让编译器决定何时int&, float
比推导U&, T
更好。