SFINAE enable_if explicit constructor

I am trying to switch between an explicit and an implicit conversion constructor using enable_if .

My code currently looks like

 #include <type_traits> #include <cstdint> enum class enabled {}; template <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type; template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type; template <std::intmax_t A> struct SStruct { static constexpr std::intmax_t a = A; }; template <typename T> struct SCheckEnable : std::integral_constant<bool, T::a == 0> { }; template <typename U, typename T> class CClass { public: template <typename T2, enable_if_t<SCheckEnable<U>::value, enabled>...> constexpr CClass(T2 v) : val(v) {}; template <typename T2, disable_if_t<SCheckEnable<U>::value, enabled>...> explicit constexpr CClass(T2 v) : val(v) {}; private: T val; }; int main() { CClass<SStruct<0>, double> a = 1; // should use implicit constructor CClass<SStruct<1>, double> b = CClass<SStruct<1>, double>(1); // should use explicit constructor } 

true in enable_if depends on the template parameter U

If I try to compile this minimal example with g++ 4.9.1 and --std=c++11 , I get the following errors

 sfinae.cpp: In substitution of 'template<bool B, class T> using disable_if_t = typename std::enable_if<(! B), T>::type [with bool B = true; T = enabled]': sfinae.cpp:13:52: required from here sfinae.cpp:7:95: error: no type named 'type' in 'struct std::enable_if<false, enabled>' template <bool B, typename T = void> using disable_if_t = typename std::enable_if<!B, T>::type; ^ sfinae.cpp:19:68: error: prototype for 'constexpr CClass<U, T>::CClass(T2)' does not match any in class 'CClass<U, T>' template <typename U, typename T> template <typename T2> constexpr CClass<U, T>::CClass(T2 v) : val(v) ^ sfinae.cpp:13:77: error: candidates are: template<class U, class T> template<class T2, int ...<anonymous> > constexpr CClass<U, T>::CClass(T2) template <typename T2, disable_if_t<true, enabled>...> explicit constexpr CClass(T2 v); ^ sfinae.cpp:12:67: error: template<class U, class T> template<class T2, enabled ...<anonymous> > constexpr CClass<U, T>::CClass(T2) template <typename T2, enable_if_t<true, enabled>...> constexpr CClass(T2 v); ^ 

Any idea how to choose between explicit and implicit plotting based on parameter U here?

+7
c ++ c ++ 11 templates sfinae enable-if
source share
1 answer

Using

 template <class...> struct null_v : std::integral_constant<int, 0> {}; 

and define the constructors as

 template <typename T2, long = null_v<enable_if_t<SCheckEnable<U>::value, T2>>::value> constexpr CClass(T2 v) : val(v) {}; template <typename T2, int = null_v<disable_if_t<SCheckEnable<U>::value, T2>>::value> explicit constexpr CClass(T2 v) : val(v) {}; 

Make the argument dependent and actually instantiated. Demo

[temp.deduct] / 8:

If the substitution results in an invalid type or expression, enter the deduction ends. An invalid type or expression is one that is poorly formed if written using substituted arguments .

In your case, an error occurs outside of any substitution, therefore, without causing a deduction failure, but rather makes your code poorly formed.

+3
source share

All Articles