I thought the following code would compile because conflicting overloads are SFINAEd away. But the compiler (GCC) says: void Foo<X>::bar(Xd) const' cannot be overloaded
. Is there an easy to way to fix it, or would I have to specialize the whole of 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(){}
From the reference for 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
};