use*_*436 4 c++ linker templates specialization c++11
当模板参数类型相同时,我试图专门化两个模板参数的功能.我这样做的方式如下:
#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;
}
Run Code Online (Sandbox Code Playgroud)
这段代码编译得很好(GCC 4.8.2),但链接器给出了所有fun调用时未定义的引用,U并且T类型相同.为什么不起作用?
链接器输出:
g++ -std=c++11 test.cpp
Run Code Online (Sandbox Code Playgroud)
/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
Run Code Online (Sandbox Code Playgroud)
问题
您fun正在使用std::enable_if保护instatiation从两种类型的不同,有一个重大问题; 它不能隐含地推断出类型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;
}
Run Code Online (Sandbox Code Playgroud)
在上面,编译器可以推导出两者T并且U在我们的模板中,也不需要对所述模板进行明确的专门化; 我们可以利用C++的重载规则,让编译器决定什么时候int&, float比推导更好U&, T.