Select 函数基于模板是 pointer/reference 还是 none

Select function based on if template is pointer/reference or none

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

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: error: redefinition of 'template void f(T&&)'

7:13: note: 'template void f(T&&)' previously declared here

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

关于如何修复它或简化此代码的任何想法。

模板默认参数值不是签名的一部分,因此您需要通过添加额外的虚拟模板参数来进一步消除重载的歧义:

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)
{}

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

#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]$