这种语法是非法的吗?

时间:2015-01-11 15:27:38

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

以下内容无法在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'之前抱怨[错误]预期')'它虽然在Visual Studio 2013上编译,我想知道VS2013是否正确接受它。当我在Tag之外声明Base<T>时,它会编译,但我想在Tag内声明它所属的Base<T>。使用Derived(Base<T>::Tag tag) : Base<T>(tag) {}也无济于事。任何方法可以解决上述问题,以便两个编译器都接受这一点,同时将Tag保留在Base<T>内。

1 个答案:

答案 0 :(得分:3)

[temp.dep] / 3:

  

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

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

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