Reputation: 302718
Why is it that this compiles:
class Testable {
public:
template <bool flag>
typename std::enable_if<flag>::type
void foo() { cout << "Yay" << endl; }
template <bool flag>
typename std::enable_if<!flag>::type
void foo() { cout << "Nay" << endl; }
};
But not if I define both foos using default types like so:
template <bool flag, typename = typename std::enable_if<flag>::type>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, typename = typename std::enable_if<!flag>::type>
void foo() { cout << "Nay" << endl; } // (B)
I get this error (first line pointing to the definition of (B)
, second one pointing to (A)
):
error: 'template<bool flag, class> void Testable::foo()' cannot be overloaded
error: with 'template<bool flag, class>> void Testable::foo()'
Upvotes: 11
Views: 2803
Reputation: 275260
As noted, two functions cannot have the same signature.
However, I have a different fix.
template<std::size_t>
struct secret_enum { enum class type {}; };
template<bool b, std::size_t n=0>
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type;
class Testable {
public:
template <bool flag, EnableIf<flag, 0>...>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, EnableIf<!flag, 1>...>
void foo() { cout << "Nay" << endl; } // (B)
};
where you enumerate your overloads with 0
, 1
, etc, which generates a possible type, which you then ...
to say "0 or more of these", and the types generated are basically impossible to generate enum
instances.
Sadly, this doesn't work in clang 3.2. It does in gcc 4.8.
Upvotes: 1
Reputation: 126412
The compiler complains because the two function templates have the same signature. Paragraph 1.3.18 of the C++11 Standard specifies what the signature of a function template is defined by:
<function template>
name, parameter type list (8.3.5), enclosing namespace (if any), return type, and template parameter list
As you can see, default template arguments are not part of the signature.
You could work around this problem by changing your definition of Testable
as follows:
class Testable {
public:
template <bool flag, typename std::enable_if<flag>::type* = nullptr>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, typename std::enable_if<!flag>::type* = nullptr>
void foo() { cout << "Nay" << endl; } // (B)
};
Upvotes: 11