根据模板是指针/引用还是不选择来选择函数

时间:2018-11-28 16:17:16

标签: c++ c++11 sfinae

我想提供一个函数的不同实现,具体取决于它是指针,引用还是常规类型。到目前为止,这是我的代码:

template<class T,
         class = typename std::enable_if_t<std::is_reference<T>::value>>
void f(T && in)
{}

// This causes redefinition error 
template<class T,
    class = typename std::enable_if_t<std::is_pointer<T>::value>>
void f(T && in)
{}

template<class T,
    class = typename std::enable_if_t<!std::is_reference<T>::value>,
    class = typename std::enable_if_t<!std::is_pointer<T>::value>>
void f(T && in)
{}

中间函数导致:

  

12:13:错误:重新定义了'template void f(T &&)'

     

7:13:注意:先前声明的'template void f(T &&)'   这里

有趣的是,只有第一个和最后一个函数可以一起编译。

关于如何解决或简化此代码的任何想法。

2 个答案:

答案 0 :(得分:10)

通常的方法是提供适当的重载:

#include <iostream>

template <class T> void f(T&&) {
    std::cout << "T&&\n";
}

template <class T> void f(T*) {
    std::cout << "T*\n";
}

template <class T> void f(T&) {
    std::cout << "T&\n";
}

int main() {
    int i;
    f(std::move(i));
    f(&i);
    f(i);
}

这将产生以下输出:

[temp]$ clang++ -std=c++11 test.cpp
[temp]$ ./a.out
T&&
T*
T&
[temp]$ 

答案 1 :(得分:5)

模板默认参数值不是签名的一部分,因此您需要进一步消除歧义,例如-添加一个额外的虚拟模板参数:

template<class T,
         class = typename std::enable_if_t<std::is_reference<T>::value>>
void f(T && in)
{}

// This causes redefinition error 
template<class T,
    class = typename std::enable_if_t<std::is_pointer<T>::value>, class = void>
void f(T && in)
{}