为什么标准中不允许初始化模板参数列表中的常量相关types?
在对这篇文章的回答“ (部分地)专门化非依赖types的非types模板参数 ”中,它指出:
对应于专门的非types参数的模板参数的types不应该依赖于专门化的参数。 [例如:
template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error
– 例子]
我的问题是为什么这个限制在这里? 至less有一个用例,我发现这个限制干扰了编写干净的代码。 例如
template <typename T, T*> struct test; template <typename T> struct test<T, nullptr> // or struct test<T, (T*)nullptr> { }; template <typename R, typename...ARGs, R(*fn)(ARGs...)> struct test<R(ARGs...), fn> { };
虽然我不确定是否还有其他一些基于types的常量是不成问题的问题。
任何人都有这样的原因吗?
(恕我直言)标准不允许某个特定function的最常见的原因是:
- 该function被另一种语言机制所覆盖,使其变得多余。
- 它与现有的语言逻辑和实现相矛盾,使得它的实现有可能破译。
- 遗产:这个function首先被排除在外,现在我们已经build立了很多没有它的function,几乎被遗忘了(请参阅部分function模板专门化)。
实现的难度很less是一个因素,尽pipe编译器实现可能需要一些时间才能赶上“硬”东西的进化。
您始终可以将您的非types模板参数封装在另一个types中:
template < typename T1, typename T2 > struct Demo {}; // primary template template < typename T > struct Demo<T, integral_constant<T, 0>> {}; // specialization
我怀疑这种攻击是否属于案例1.案例3总是一种可能性,所以我们来看案例2.为此,我们必须知道标准对类模板部分专业化的相关规则。
14.5.5 类模板部分专业化
如果非types参数是非types参数的名称,则它是非专用的。 所有其他非types的参数都是专门的。 (C1)
在类模板部分特化的参数列表中,下列限制适用:
- 除非参数expression式是简单标识符,否则部分专用的非types参数expression式不应包含部分特化的模板参数。 (C2)
- 对应于专门的非types参数的模板参数的types不应该依赖于专门化的参数。 (C3)
我标出了我认为相关的前三位C (第三位是有问题的)。 根据我们的情况C1, 我们有一个专门的非types的论点,所以C2应该站立,但这
template <class T, T t> struct C {}; template <class T> struct C<T, 1>;
实际上是
template <class T, T t> struct C {}; template <class T> struct C<T, T(1)>; // notice the value initialization
所以部分专用的非types参数T t
在除标识符以外的expression式中涉及部分专用化class T
的模板参数; 而且这样的专业化必然涉及到class T
的价值初始化,这将永远是违反规则的。 然后C3出现,为我们清除了这个问题,这样我们就不用每次都去扣除了。
到目前为止,我们已经确定规则与他们自己同步,但是这不能certificate情况2(一旦我们删除了最初的限制,其他所有相关的限制就会分崩离析)。 我们不得不深入匹配类模板的部分特殊化规则; 部分sorting在这里被认为是超出范围的,因为如果我们能够产生有效的候选者,那么由程序员来组装一个合适的程序(即不会产生类模板的模棱两可的用法)。
部分
类模板部分特化的匹配[temp.class.spec.match]
描述了在模板专门化中涉及(给与或带)的“模式匹配”过程。 规则1
是程序的总体工作stream程,后面的规则是定义正确性的规则
如果可以从实际的模板参数列表中推导出部分特化的模板参数,则部分特化与给定的实际模板参数列表相匹配
非模板参数也可以从主模板的非types参数的实际模板参数的值中推导出来。
在引用类模板专业化的types名称(例如A)中,参数列表应与主模板的模板参数列表相匹配。 专业化的模板参数是从主模板的参数中推导出来的。
通过允许对应于特定非types参数的模板参数的types依赖于特化的参数, 这些规则不被违反 。 所以恕我直言,没有具体的理由,为什么我们不能在这个语言的未来版本中有这个function: 遗产是责备 。 可悲的是,我没有设法find任何语言的build议,主动介绍这个function。