在对这篇文章"(部分)专门化依赖类型的非类型模板参数。“的答复中,它指出:
与专用的非类型参数相对应的模板参数的类型不应依赖于专门化的参数。[例子: 模板<类T,T t>结构C {};模板结构C;// template< int X,int (*array_ptr)X >类A {};int array5;template< int X>类A { };//错误 -end示例]
我的问题是为什么这里有这个限制?至少有一个用例,我发现这个限制会干扰编写干净的代码。例如。
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>
{
};
虽然我不确定是否还有其他的情况,基于类型的常量声明是一个问题,除了没有任何意义。
有人有理由这么做吗?
发布于 2015-09-06 10:05:23
(IMHO)标准不允许某一特定功能的最常见的原因是:
实现的困难很少是一个因素,尽管编译器实现可能需要一些时间才能赶上“困难”方面的发展。
您可以始终将非类型模板参数包装为另一种类型:
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 类模板部分专门化
- A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier. **(C2)**
- The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. **(C3)**
我标记了我发现相关的前三个Clauses (第三个是有问题的)。根据C1 (在我们的例子中是),我们有一个专门的非类型参数,所以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
因此,部分专门化的非类型参数T t
在标识符以外的表达式中涉及部分专门化class T
的模板参数;此外,此类专门化必然会在值初始化中涉及class T
,这将始终违反规则。然后C3来为我们清除这一切,这样我们就不用每次都做那个推论了。
到目前为止,我们已经确定规则与自己是同步的,但这并不能证明情况2(一旦我们删除了最初的限制,所有其他相关的限制就会分崩离析)。我们必须深入研究匹配类模板、部分专门化的规则;偏序在这里被认为超出了范围,因为如果我们能够产生有效的候选项,则由程序员来组合一个格式良好的程序(即不创建类模板的模糊用法)。
部分
类模板部分专门化的匹配temp.class.spec.match
描述模板专门化所涉及的(给予或接受)“模式匹配”过程。规则1
是过程的整体工作流程,随后的规则是定义正确性的规则。
这些规则不违反,因为允许与专门化的非类型参数对应的模板参数的类型依赖于专门化的参数。因此,IMHO 没有明确的理由为什么不能在将来的语言修订版中使用这个特性:遗留问题应该归咎于。遗憾的是,我没有找到任何语言提案,主动引入这一功能。
https://stackoverflow.com/questions/32104890
复制