I have the following code (sorry for the large code chunk, but I could not narrow it down any more)
template <bool B>
struct enable_if_c {
typedef void type;
};
template <>
struct enable_if_c<false> {};
template <class Cond>
struct enable_if : public enable_if_c<Cond::value> {};
template <typename X>
struct Base { enum { value = 1 }; };
template <typename X, typename Y=Base<X>, typename Z=void>
struct Foo;
template <typename X>
struct Foo<X, Base<X>, void> { enum { value = 0 }; };
template <typename X, typename Y>
struct Foo<X, Y, typename enable_if<Y>::type > { enum { value = 1 }; };
int main(int, char**) {
Foo<int> foo;
}
but it fails to compile with gcc (v4.3) with
foo.cc: In function ‘int main(int, char**)’:
foo.cc:33: error: ambiguous class template instantiation for ‘struct Foo<int, Base, void>’
foo.cc:24: error: candidates are: struct Foo<X, Base<X>, void>
foo.cc:27: error: struct Foo<X, Y, typename enable_if<Y>::type>
foo.cc:33: error: aggregate ‘Foo<int, Base<int>, void> foo’ has incomplete type and cannot be defined
ok, so it's ambiguous. but I was'nt expecting it to be a problem as when using specialization it will almost always be some ambiguity. However this error is only triggered when using the class with enable_if<...>, if I replace it with a class like the following there is no problem.
template <typename X, typename Y>
struct Foo<X, Y, void > { enum { value = 2 }; };
why does this class not cause a ambiguity while the other do? isn't the two the same thing for classes with a true ::value? anyway, any hints as to what im doing wrong is appreciated.
Thanks for the answers, my real problem (to get the compiler to select my first specialization) was solved by replacing struct Foo<X, Base<X>, void>
with struct Foo<X, Base<X>, typename enable_if< Base<X> >::type >
. Which seems to work the way I want.