I have two class specializations. I want one of them to be used when T::A exists and the other to be used when T::B exists, which should be multually exclusive in practice. I am using std::void_t< decltype( ... ) > to test for existence. I expect that expression to fail to evaluate for either one or the other specialization, and so I expect SFINAE to cause one of the specializations to be ignored.
template< typename T, typename Enable = void >
class C{};
template< typename T >
class C< T, std::void_t< decltype( T::A ) > > {};
template< typename T >
class C< T, std::void_t< decltype( T::B ) > > {};
However, MSVC just gives me
(On line containing T::B): error C2953: 'C<T,void>': class template has already been defined
(On line containing T::A): note: see declaration of 'C<T,void>'
What am I doing wrong?
CodePudding user response:
Clang also rejects this code, but not GCC. This is not the first time I'm seeing problems with std::void_t
.
I would stay away from it, and prefer decltype(void(T::A))
.
Or you can define your own robust void_t
(code taken from cppreference):
template<typename... Ts> struct make_void { typedef void type; };
template<typename... Ts> using void_t = typename make_void<Ts...>::type;