Search code examples
c++templatessfinaetemplate-specialization

"Class template has already been defined" when making similar but different specializations


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?


Solution

  • 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;