#include <type_traits>
struct A {};
template <class T, class = std::enable_if_t<std::is_same_v<T, A>>>
void foo(T t) {}
template <class T, class = std::enable_if_t<!std::is_same_v<T, A>>>
void foo(T t) {}
int main()
{
foo(A{});
foo(0);
return 0;
}
我看到foo()
的第二个定义的编译错误:
test.cpp:9:6: error: redefinition of ‘template<class T, class> void foo(T)’
之所以这样,是因为SFINAE解析发生在后期。
作为一种解决方法,我可以通过将其更改为第二个foo()
来向其添加一个模板参数:
template <class T, class = std::enable_if_t<!std::is_same_v<T, A>>, class = void>
void foo(T t) {}
然后错误消失了。但是我想知道还有没有更多惯用的方式来处理这种冲突的过载?对于两个重载,添加一个额外的虚拟模板参数就足够了,但是如果我们有很多这样的重载,那么代码将变得更加混乱,而且乍看之下,这些额外参数的用途一目了然。
答案 0 :(得分:2)
但是我想知道还有更多惯用的方法来处理这种冲突的过载吗?
通过示例
template <class T, std::enable_if_t<std::is_same<T, A>{}> * = nullptr>
void foo(T t) {}
template <class T, std::enable_if_t<!std::is_same<T, A>{}> * = nullptr>
void foo(T t) {}
但是我发现这种方式更加清晰
template <class T>
std::enable_if_t<std::is_same<T, A>{}> foo(T t) {}
template <class T>
std::enable_if_t<!std::is_same<T, A>{}> foo(T t) {}
您还可以添加第二个默认参数。
template <class T>
void foo(T t, std::enable_if_t<std::is_same<T, A>{}> * = nullptr) {}
template <class T>
void foo(T t, std::enable_if_t<!std::is_same<T, A>{}> * = nullptr) {}