这个问题让我思考。有时,如果无法定义参数的公共typedef
,从类模板特化中获取实际参数很有用。在 C++03 中,这是模板设计不佳或设计意图相反的标志,并不特别常见。但是可变参数模板使 typedef 覆盖变得不可能,所以如果有一个工具来解决这个问题而不需要额外的工作,那就太好了。
C++0x 解决了typedef
一个特定可变参数模板的问题,tuple
.
tuple_element< 2, tuple< char, short, int > >::type my_int; // nth element type
但未tuple_element
结婚tuple
;它也适用于pair
and array
。它的声明没有提到tuple
.
template< size_t index, typename something_like_a_tuple >
struct tuple_element; // general case is left incomplete, unimplemented
tuple
通过部分专业化相关:
template< size_t index, typename ... tuple_elements >
struct tuple_element< index, tuple< tuple_elements ... > > { // impl. in here
但它不需要。模板模板参数可以匹配tuple
,以及仅在类型上参数化的任何其他模板。
template< size_t index,
template< typename ... > class template_over_types,
typename ... types >
struct tuple_element< index, template_over_types< types ... > > {
这将允许
tuple_element< 1, almost_any_template< char, int > >::type my_int;
tuple_element< 0, pair< int, char > >::type another_int; // same specialization
并允许额外的专业化array
template< size_t index, typename element, size_t extent >
struct tuple_element< index, array< element, extent > >
{ typedef element type; }
不可能发生冲突,因为array
' 的第二个参数是 a size_t
,而不是类型。
不幸的是,允许用户tuple_element
为他们自己的类型专门化接口。用户的先决条件及其保证由 C++0x §17.6.3.2.1/1 给出:
只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,程序才能将任何标准库模板的模板特化添加到命名空间 std。
因此,一般特化不仅不能与特化冲突array
,而且不能与任何命名用户定义类型的特化冲突。也就是说,如果用户声明了一个特化,通用参数 getter 的存在不会影响它是否被选择。
当实例化中出现歧义时(即,两个部分特化匹配一个参数列表),比较备选方案以确定哪个最特化,换句话说,最不通用。调用备选方案 A 和 B。这意味着,如果 A 可以完成 B 的工作,但 B 不能完成 A 的工作,则 B 更专业。A是通才。将选择 B。不考虑引发实例化的实际参数,因为已知它们与两个候选者都匹配。
由于我们希望通用模板遵循其他所有内容,因此我们处于良好状态。
通过用唯一的虚拟类型替换 A 中的部分特化参数来检查通用性,并检查 B 是否也可以实现这样的特化。以相反的角色重复,如果获得相反的结果,则已知一名候选人更专业。
用户特化中用户定义类型的存在保证了它的优先级,因为在参数-getter 中必须有一个与之不匹配的唯一虚拟类型。
例如,这是一个非常通用的用户声明的专业化。它tuple_element
为包含给定的任何类型参数化模板定义user_type
。
template< size_t I,
template< typename ... > class any_template,
typename ... T, typename ... U >
struct tuple_element< I, any_template< T ..., ::user_type, U ... > >;
序列..., user_type, ...
可以由一般情况处理,但用户的情况不能处理完全由人工唯一类型组成的序列,因为它不会包含user_type
.
如果任何用户专业化是候选者,它将是更优秀的。
(该标准确实在伪代码中为 指定了一个单独的部分tuple
特化,但在 as-if 规则下可以省略它。无论如何,如果实施,它将被相同的优先规则覆盖,以保护用户。)
我没有对部分排序规则进行很多尝试。这个分析正确吗?实现是否可以通过 公开通用模板索引器std::tuple_element
?