模板化函数专精:链接器错误

时间:2014-05-25 19:39:28

标签: c++ templates c++11 linker specialization

当模板参数类型相同时,我试图专门化两个模板参数的功能。我这样做的方式如下:

#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)但链接器在funU相同类型时为所有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

1 个答案:

答案 0 :(得分:5)

问题

正在使用fun来保护两种不同类型的实例的std::enable_if有一个主要问题;它不能隐式推断类型T

这意味着当您使用funb1作为参数调用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;
}

在上面,编译器可以在我们的模板中推导TU,也不需要所述模板的显式特化;我们可以使用C ++的重载规则,并让编译器决定何时int&, float比推导U&, T更好。