【问题标题】:Is this syntax illegal?这种语法非法吗?
【发布时间】:2015-01-11 15:27:37
【问题描述】:

以下内容无法在 GCC 4.8.1 上编译:

//struct Tag {};  // Program compiles if I use this.

template <typename T>
struct Base {
    struct Tag {};
    Base(Tag) {}
};

template <typename T>
struct Derived : Base<T> {
    Derived(Tag tag) : Base<T>(tag) {}
//  Derived(Base<T>::Tag tag) : Base<T>(tag) {}
};

int main() {}

在 'tag' 之前抱怨 [Error] 应为 ')'。虽然它在 Visual Studio 2013 上编译,但我想知道 VS2013 是否正确接受它。当我在Base&lt;T&gt; 之外声明Tag 时它会编译,但我想在它所属的Base&lt;T&gt; 内声明Tag。使用Derived(Base&lt;T&gt;::Tag tag) : Base&lt;T&gt;(tag) {} 也无济于事。解决上述问题的任何方法,以便两个编译器都接受这一点,同时将 Tag 保留在 Base&lt;T&gt; 内。

【问题讨论】:

  • 您的代码可以使用 Visual Studio 正常编译。
  • 我知道,我说过。但我希望它在两个编译器上都能编译。所以你是说语法是合法的?
  • 使用Derived(typename Base&lt;T&gt;::Tag tag) : Base&lt;T&gt;(tag) {},因为Base&lt;T&gt;是从属名称
  • 啊太棒了!谢谢你。问题解决了。但我仍然想知道原始代码是否合法。

标签: c++ templates language-lawyer name-lookup


【解决方案1】:

[temp.dep]/3:

在类或类模板的定义中,如果是基类 取决于模板参数,不检查基类范围 在非限定名称查找期间,无论是在定义点 类模板或成员或在类的实例化期间 模板或成员。

Tag 用作非限定名称 - 因此它永远不能指定依赖基类的成员。但是,Tag 也不是依赖的,因此必须在定义时(实例化之前)解析查找,这使得程序格式错误。这可以在定义或实例化时进行诊断。

但是,当名称是依赖的(如 Base&lt;T&gt;::Tag)时,名称查找会被推迟,并在实例化时考虑依赖基类的成员。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-26
    • 2016-02-11
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    • 1970-01-01
    相关资源
    最近更新 更多