template<typename T,typename... Ts> class C{
public:
C(typename enable_if_A<T>::type const &p){cout << "A" << endl;}
C(typename enable_if_B<T>::type const &p){cout << "B" << endl;}
};
This is wrong, but you already knew that :) The reason is that SFINAE can only be applied at a template level, but you are trying to apply it to a member of the template. That is, SFINAE in your template above can only be applied to different C<T>
types, but not the constructors of the C<T>
.
To be able to apply SFINAE to the constructor, you need to make the constructor a template. But in your case that will lead to another limitation. Constructors are special functions for which you cannot provide a template argument (even if the constructor is templated), which means that the template type must be deduced from the place of call. But nested types are not deducible...
You can work around the limitation by changing the signature of the constructor:
template <typename T>
template <typename U>
C<T>::C<U>(A<U> const & r, typename enable_if_A<U>::type* _ = 0) {
// ...
}
In this case the class C
is a template that has a templated constructor taking a A<U>
, which can only be used for types for which enable_if_A<U>::type
is indeed a type. The type can be deduced at the place of call through the first argument, and the deduced type U
will be substituted on the second argument. If that substitution fails the templated constructor will be discarded.
The solution above is C++03 compatible. If you have a C++11 compiler you can do the same without the need of the extra argument to the constructor (i.e. without adding an extra argument; not 100% if I am getting the syntax right :)):
template <typename T>
template <typename U, typename _ = typename enable_if_A<U>::type>
C<T>::C<U>(U const &) {...}