I wonder whether it is possible to put the whole code of such a class inside the class (kind of as in Java). I\'m doing this for some piece of code, instead of having to search
Yes, it is possible to have everything in a single class definition without specializations, using std::enable_if
to choose the appropriate constructor like this:
template <bool C, typename T = void>
using only_if = typename std::enable_if <C, T>::type;
template <typename A, typename B>
using eq = typename std::is_same <A, B>::type;
template <class V> class A {
public:
template <typename D = int, only_if <!eq <V, bool>{}, D> = 0>
A() { std::cout<<"Generic"<<std::endl; };
template <typename D = int, only_if <eq <V, bool>{}, D> = 0>
A() { std::cout<<"bool"<<std::endl; }
};
where template aliases only_if
and eq
are just for brevity.
Template parameter D
is dummy. Usually we apply enable_if
on a template parameter, a function argument, or a return type. A non-template default constructor is a unique exception having nothing of the above, hence the dummy.
This approach is maybe an overkill for this simple example, where a template specialization may be simpler. But a class of 30 lines of code that needs a specialization like that for just one constructor will be definitely simpler this way rather than duplicating all code for the entire class specialization. One may argue that in this case the code may be refactored using a base class that contains only what needs to be specialized. However:
There are also cases where you don't want to choose between two constructor versions, but only to enable or disable a single version according to a type predicate, e.g. whether a type is std::default_constructible
or not.
Or, you may need to decide whether a constructor is declared explicit
or not, again depending on a type predicate (so, provide an explicit and a non-explicit version).
In such cases, enable_if
is very convenient.
Check here an example of a very generic tuple implementation with five constructors, all using enable_if
, and one (the default) using a dummy template parameter. The remaining four are for the combinations of explicit vs. non-explicit and element-list vs other-tuple.
Yes.
It is completely possible though the specialization must be done in other template.
#include <iostream>
template <class V> class A {
public:
A() {
std::cout<<"Generic"<<std::endl;
};
};
template <> class A<bool>
{
public:
A() { std::cout << "Bool specialization" << endl; }
};
int main(int argc, char** argv) {
A<int> a;
A<bool> b;
}