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.