Reputation: 3433
I've been messing around with enable_if, and I seem to have stumbled upon some inconsistent behaviour. This is in VS2010. I've reduced it to the following sample.
#include <type_traits>
using namespace std;
// enable_if in initial template definition
template <class T, class Enable = enable_if<true>> struct foo {};
foo<int> a; //OK
// explicit specialisation
template <class T, class Enable = void> struct bar;
template <class T> struct bar<T, void> {};
bar<int> b; //OK
// enable_if based specialisation
template <class T, class Enable = void> struct baz;
template <class T> struct baz<T, std::enable_if<true>> {};
baz<int> c; //error C2079: 'c' uses undefined struct 'baz<T>'
Is this a bug in the code or the compiler?
Upvotes: 1
Views: 4681
Reputation: 27623
Your problem has very little to do with enable_if
// you declare a structure named baz which takes 2 template parameters, with void
// as the default value of the second one.
template <class T, class Enable = void> struct baz;
// Partial specialization for a baz with T and an std::enable_if<true>
template <class T> struct baz<T, std::enable_if<true>> {};
// Declare a baz<int, void> (remember the default parameter?):
baz<int> c; //error C2079: 'c' uses undefined struct 'baz<T>'
baz<int, void>
has an incomplete type at that point. The same problem will occur without enable_if
:
template <class T, class U = void>
struct S;
template <class T>
struct S<T, int>
{ };
S<double> s;
And, as James said, you're using enable_if
incorrectly. Boost's documentation for enable_if
does a great job explaining it.
Upvotes: 3
Reputation: 354979
std::enable_if<true>
should be typename std::enable_if<true>::type
.
std::enable_if<true>
always names a type (as does std::enable_if<false>
). In order to get substitution to fail when the condition is false you need to use the type
nested typedef, which is only defined if the condition is true.
Upvotes: 6