【问题标题】:Template alias scope模板别名范围
【发布时间】:2015-09-24 18:03:50
【问题描述】:

根据http://en.cppreference.com/w/cpp/language/type_alias,别名是块级声明。它没有说明模板别名有什么特别之处,因此应该理解模板别名也是块级声明。

但是,在块级别使用模板别名是不可能的。错误因编译器而异 - 虽然 g++ 给出了一个有意义的消息,说模板在块范围内是不允许的,但 clang 是完全神秘的。 (例如:http://coliru.stacked-crooked.com/a/0f0862dad6f3da61)。

到目前为止我的问题:

  • cppreference 是否未能指定模板别名不能在块范围内使用? (或者我需要参加阅读课程吗?)
  • 编译器在块级拒绝模板别名方面是否正确(我发现这个功能对我的特殊编码习惯非常有趣)
  • 如果第二个答案是肯定的,这可能是什么原因?为什么编译器会拒绝我这种纯语法糖?

【问题讨论】:

  • 重新“纯语法糖”,不,不是这样。然而,我刚起床,我的神经元还没有完全投入。其他人将不得不详细说明。

标签: c++ template-aliases


【解决方案1】:

别名模板是 [temp.alias]

声明是别名声明(第 7 条)的模板声明将标识符声明为 是一个别名模板。别名模板是一系列类型的名称。别名模板的名称是 模板名称。

如果我们看一下 14.2 [temp] 我们有

模板声明只能作为命名空间范围或类范围声明出现。在一个函数中 模板声明,declarator-id 的最后一个组成部分不能是 template-id。

所以是的,cppreference 说它可以在块范围内声明并且您的编译器是正确的。如果你点击block declarations的链接,它会带你到一个声明列表,它有Template declaration,在那里它有

类(包括结构体和联合体)、成员类或成员枚举类型、函数或成员函数、命名空间范围内的静态数据成员、类范围内的变量或静态数据成员的声明,(C+ +14) 或别名模​​板 (C++11 起) 它还可以定义模板特化。

至于为什么标准说模板只能在命名空间范围或类范围内声明我喜欢James Kanzeanswer

这个问题可能与模板的历史实现方式有关:早期的实现技术(有些至今仍在使用)要求模板中的所有符号都具有外部链接。 (实例化是通过在单独的文件中生成等效代码来完成的。)在函数内部定义的名称永远不会有链接,并且不能在定义它们的范围之外引用。

【讨论】:

  • 好的,编译器的行为符合标准。现在,你知道我最后一个问题的答案了吗?
  • @SergeyA 你什么意思?您的最后一个问题没有实际意义,因为我们无法在块范围内声明模板。
  • 好吧,这不是模板声明(即使按照标准如此标记)。它是模板别名声明,这两者之间是有区别的。同样,我看到 templare 别名是一种纯语法糖。禁止在块范围内声明它的原因是什么?如果允许它会破坏什么?
  • @SergeyA 不,没有区别。您仍然必须使用别名模板指定类型。以template<class T> using vec2d = std::vector<std::vector<T>>; 为例,当我们使用vec2d 时,我们仍然需要指定类型,例如vec2d<int> foo; 如果您使用的是模板关键字,那么它就是一个模板声明。
  • 这很好。问题是,为什么它被禁止。应该有一个原因,比如编译器无法处理它,它会不安全等等。一些原因。我没看到。 template using ve2d = std::vector > 只是一个简写。因此,每当编译器看到 ve2d 时,它都可以将其扩展为 std::vector<:vector> > 。我不明白为什么需要禁止。这就是我要问的问题。
【解决方案2】:

编译器的行为正确。

C++14 标准第 14 节:

模板声明只能作为命名空间范围或类出现 范围声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多