首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么标准不允许初始化模板参数列表中的常量依赖类型?

为什么标准不允许初始化模板参数列表中的常量依赖类型?
EN

Stack Overflow用户
提问于 2015-08-19 20:17:44
回答 1查看 1.5K关注 0票数 35

在对这篇文章"(部分)专门化依赖类型的非类型模板参数。“的答复中,它指出:

与专用的非类型参数相对应的模板参数的类型不应依赖于专门化的参数。[例子: 模板<类T,T t>结构C {};模板结构C;// template< int X,int (*array_ptr)X >类A {};int array5;template< int X>类A { };//错误 -end示例]

我的问题是为什么这里有这个限制?至少有一个用例,我发现这个限制会干扰编写干净的代码。例如。

代码语言:javascript
代码运行次数:0
运行
复制
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>
{
};

虽然我不确定是否还有其他的情况,基于类型的常量声明是一个问题,除了没有任何意义。

有人有理由这么做吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-06 18:05:23

(IMHO)标准不允许某一特定功能的最常见的原因是:

  1. 该特性被语言中的另一种机制所覆盖,因此它是多余的。
  2. 它与现有的语言逻辑和实现相矛盾,使其实现有可能中断代码。
  3. 遗留:这个特性一开始就被忽略了,现在我们已经构建了很多没有它的特性,以至于它几乎被遗忘了(请参阅部分函数模板专门化)。

实现的困难很少是一个因素,尽管编译器实现可能需要一些时间才能赶上“困难”方面的发展。

您可以始终将非类型模板参数包装为另一种类型:

代码语言:javascript
代码运行次数:0
运行
复制
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 类模板部分专门化

  1. 如果非类型参数是非类型参数的名称,则非类型参数是非专用的.所有其他非类型参数都是专门化的。(C1)
  2. 在类模板部分专门化的参数列表中,适用以下限制:
代码语言:javascript
代码运行次数:0
运行
复制
- 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应该支持,但是这是

代码语言:javascript
代码运行次数:0
运行
复制
template <class T, T t> struct C {};
template <class T> struct C<T, 1>;

实际上是

代码语言:javascript
代码运行次数:0
运行
复制
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是过程的整体工作流程,随后的规则是定义正确性的规则。

  1. 如果可以从实际模板参数列表中推导出部分专门化的模板参数,则部分专门化与给定的实际模板参数列表匹配。
  2. 非类型模板参数也可以从主模板的非类型参数的实际模板参数的值中推导出来。
  3. 在引用类模板专门化的类型名称中,参数列表应与主模板的模板参数列表匹配。专门化的模板参数是从主模板的参数中推导出来的。

这些规则不违反,因为允许与专门化的非类型参数对应的模板参数的类型依赖于专门化的参数。因此,IMHO 没有明确的理由为什么不能在将来的语言修订版中使用这个特性:遗留问题应该归咎于。遗憾的是,我没有找到任何语言提案,主动引入这一功能。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32104890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档