I have the following code:
#include <iostream>
template <class T, typename U = void> class A;
template <class T>
class C
{
public:
typedef T Var_t;
};
template <class T>
class B : public C<T>
{
};
template <class T>
class A<B<T>>
{
public:
A() { std::cout << "Here." << std::endl; }
};
template <class T>
class A<T, typename std::enable_if<
std::is_base_of<C<typename T::Var_t>, T>::value>
::type>
{
public:
A() { std::cout << "There." << std::endl;}
};
int main()
{
A<B<int>> a;
return 0;
}
When the compiler tries to instantiate the second partial specialization with the parameter B<int>, std::is_base_of<C<int>, B<int>>::value is true, and therefore the std::enable_if<...>::type returns void (the default type if one isn't specified). This causes an "ambiguous partial specialization" error as the compiler can't decide between the first and second partial specializations. So far, so good. However, when I replace the code within the std::enable_if to simply be true (i.e., the second partial specialization is just template <class T> class A<T, typename std::enable_if<true>::type>), the code compiles and runs. It outputs "Here", indicating the first specialization was chosen.
My question is: If they both evaluate to void in the end, why does the behavior of std::enable_if<true>::type differ to that of std::enable_if<std::is_base_of<...>::value>::type?
This behavior has been tested and verified on Ideone here.