SFINAE 不能防止模棱两可的运算符重载吗?
Can SFINAE not prevent ambiguous operator overloads?
我认为以下代码可以编译,因为冲突重载已被 SFINAEd 消除。但是编译器 (GCC) 说:void Foo<X>::bar(Xd) const' cannot be overloaded
。有没有一种简单的方法来修复它,或者我必须专门研究整个 Foo
?
#include <type_traits>
struct A{};
template<typename X>
struct Foo {
template<typename Xd=X, typename = std::enable_if_t<std::is_arithmetic<Xd>::value>>
void bar() const {
}
template<typename Xd=X, typename = std::enable_if_t<std::is_same<Xd,A>::value>>
void bar() const {
}
};
int main(){}
来自 the reference 对于 std::enable_if:
A common mistake is to declare two function templates that differ only
in their default template arguments. This does not work because the
declarations are treated as redeclarations of the same function
template (default template arguments are not accounted for in function
template equivalence).
/*** WRONG ***/
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
typename = std::enable_if_t<std::is_integral<Integer>::value>
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
typename = std::enable_if_t<std::is_floating_point<Floating>::value>
>
T(Floating) : m_type(float_t) {} // error: treated as redefinition
};
/* RIGHT */
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, int> = 0
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};
我认为以下代码可以编译,因为冲突重载已被 SFINAEd 消除。但是编译器 (GCC) 说:void Foo<X>::bar(Xd) const' cannot be overloaded
。有没有一种简单的方法来修复它,或者我必须专门研究整个 Foo
?
#include <type_traits>
struct A{};
template<typename X>
struct Foo {
template<typename Xd=X, typename = std::enable_if_t<std::is_arithmetic<Xd>::value>>
void bar() const {
}
template<typename Xd=X, typename = std::enable_if_t<std::is_same<Xd,A>::value>>
void bar() const {
}
};
int main(){}
来自 the reference 对于 std::enable_if:
A common mistake is to declare two function templates that differ only in their default template arguments. This does not work because the declarations are treated as redeclarations of the same function template (default template arguments are not accounted for in function template equivalence).
/*** WRONG ***/
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
typename = std::enable_if_t<std::is_integral<Integer>::value>
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
typename = std::enable_if_t<std::is_floating_point<Floating>::value>
>
T(Floating) : m_type(float_t) {} // error: treated as redefinition
};
/* RIGHT */
struct T {
enum { int_t,float_t } m_type;
template <typename Integer,
std::enable_if_t<std::is_integral<Integer>::value, int> = 0
>
T(Integer) : m_type(int_t) {}
template <typename Floating,
std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};