问题描述
当在非推导上下文中涉及模板参数的模式之间唯一区别时,多个类模板专业化名称是否有效?
Are multiple class template specialisations valid, when each is distinct only between patterns involving template parameters in non-deduced contexts?
std::void_t
的一个常见示例使用它来定义特征,该特征揭示类型是否具有称为"type"的成员typedef
.在这里,采用单个专业化.这可以扩展为识别类型是否具有 成员typedef
称为"type1",或具有一个称为"type2"的成员.下面的C ++ 1z代码可使用GCC进行编译,但不能使用Clang进行编译.合法吗?
A common example of std::void_t
uses it to define a trait which reveals whether a type has a member typedef
called "type". Here, a single specialisation is employed. This could be extended to identify say whether a type has either a member typedef
called "type1", or one called "type2". The C++1z code below compiles with GCC, but not Clang. Is it legal?
template <class, class = std::void_t<>>
struct has_members : std::false_type {};
template <class T>
struct has_members<T, std::void_t<typename T::type1>> : std::true_type {};
template <class T>
struct has_members<T, std::void_t<typename T::type2>> : std::true_type {};
推荐答案
有一个规则,即部分专业化必须比主模板更加专业化-您的两个专业都遵循该规则.但是没有一条规则规定局部专业永远不会模棱两可.更重要的是-如果实例化导致模棱两可的专业化,则程序格式错误.但是,模棱两可的实例化必须首先发生!
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!
.
.
这几乎完全是 CWG 1980 :
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();
f
的第二个声明似乎是对第一个声明的重新声明,但可以被SFINAE区分,即等效但不等同于功能.
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.
如果您使用void_t
的非别名实现:
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;
然后clang允许两个不同的专业化.当然,在同时具有type1
和type2
typedef错误的类型上实例化has_members
,但这是预料之中的.
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.
这篇关于使用void_t的多个SFINAE类模板专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!