本文介绍了使用void_t的多个SFINAE类模板专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当在非推导上下文中涉及模板参数的模式之间唯一区别时,多个类模板专业化名称是否有效?

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允许两个不同的专业化.当然,在同时具有type1type2 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类模板专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-11 01:27