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<int>, 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 wasn't 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 an ambiguity while the others do? Isn't the two the same thing for classes with a true ::value? Anyway, any hints as to what I am doing wrong are 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.