There is a rule that partial specializations have to be more specialized than the primary template – both of your specializations follow that rule. But there isn’t a rule that states that partial specializations can never be ambiguous. It’s more that – if instantiation leads to ambiguous specialization, the program is ill-formed. But that ambiguous instantiation has to happen first!
It appears that clang is suffering from CWG 1558 here and is overly eager about substituting in . void
for std::void_t
This is CWG 1980 almost exactly:
In an example like
template<typename T, typename U> using X = T; template<typename T> X<void, typename T::type> f(); template<typename T> X<void, typename T::other> f();
it appears that the second declaration of
f
is a redeclaration of the first but distinguishable by SFINAE, i.e., equivalent but not functionally equivalent.
If you use the non-alias implementation of void_t
:
template <class... Ts> struct make_void { using type = void; };
template <class... Ts> using void_t = typename make_void<Ts...>::type;
then clang allows the two different specializations. Sure, instantiating has_members
on a type that has both type1
and type2
typedefs errors, but that’s expected.