There are several issues here. The first thing is that the syntax for default template template paramers is wrong, it should be:
template <bool yes>
class Base {
public:
template<typename T=std::enable_if< yes, int>::type>
Base() { /* yes */ }
template<typename T=std::enable_if<!yes, int>::type>
Base() { /* no */ }
};
But that's not going to work either, because default parameter values are not a part of the template's signature, so, roughly speaking, this is equivalent to:
template<typename T>
Base() { /* yes */ }
template<typename T>
Base() { /* no */ }
That's how the both constructors' signatures look to the compiler. Both are templates with a single parameter, so for the purposes of overload resolutions both constructors have identical signatures, and that's not going to work any better than declaring two "Base(int foo)" constructors. You'll get the same error if you declare:
Base(int foo=0)
and
Base(int foo=1)
constructors. Two constructors, both have the same signature. Default values are not a part of a signature.
There are several traditional hacks to work around this. A common design pattern in the C++ library itself is to declare some helper empty classes and use them as additional parameters to disambiguate different methods for the purposes of overload resolution. For example, using std::in_place_t
to select a particular overloaded constructor of std::optional
, or std::in_place_type_t
, for the equivalent functionality of std::variant
's constructor.
In your case here, we can make use of the placeholder parameter completely automatic, in conjunction with delegated constructors:
#include <iostream>
struct bool_true {};
struct bool_false {};
template<bool value> class bool_value;
template<>
struct bool_value<true> {
typedef bool_true type;
};
template<>
struct bool_value<false> {
typedef bool_false type;
};
template<bool v>
using bool_value_t=typename bool_value<v>::type;
template <bool yes>
class Base {
public:
Base() : Base{ bool_value_t<yes>{} } {}
Base(const bool_true &)
{
std::cout << "Yes" << std::endl;
}
Base(const bool_false &)
{
std::cout << "No" << std::endl;
}
};
int main()
{
Base<true> t;
Base<false> f;
return 0;
}