基于 SFINAE 的重载冲突
SFINAE-based overloads conflict
#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) {}
然后错误消失了。但我想知道是否有更惯用的方法来处理这种冲突的重载?对于两个重载,添加一个额外的虚拟模板参数就足够了,但是如果我们有很多这样的重载,那么代码会变得更加混乱,并且这些额外参数的目的从乍一看到 reader.
But I am wondering is there more idiomatic way to handle such conflicting overloads?
举例
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) {}
#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) {}
然后错误消失了。但我想知道是否有更惯用的方法来处理这种冲突的重载?对于两个重载,添加一个额外的虚拟模板参数就足够了,但是如果我们有很多这样的重载,那么代码会变得更加混乱,并且这些额外参数的目的从乍一看到 reader.
But I am wondering is there more idiomatic way to handle such conflicting overloads?
举例
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) {}