8

该代码可以编译吗?

#include <iostream>

template <typename T>
struct TMPL
{
    using TP = typename T::TP; //is CL::TP visible (with T == CL)?
};

struct CL
{
    using TP = int;
    TMPL<CL>::TP val; 
};

int main()
{
    CL cl;
}

根据标准 14.6.4.1/4,在 CL 类定义之前立即实例化 TMPL

对于类模板特化,...,如果该特化被隐式实例化,因为它是从另一个模板特化中引用的,...。否则,这种特化的实例化点紧接在引用的命名空间范围声明或定义之前到专业化。

因此,CL::TP 在 TMPL 实例化点中不可见,但所有编译器(MSVC、gcc、clang)都可以正常编译。我还发现了一个缺陷报告http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287,但显然没有被接受

4

1 回答 1

2

您的示例与缺陷报告中的示例不同。在缺陷报告中,CL是一个类模板。然而,提议的解决方案的目的是使模板案例与非模板案例相同,即[basic.scope.pdecl]

6 在类成员的声明点之后,可以在其类的范围内查找成员名。[注意:即使课程是不完整的课程也是如此。例如,

struct X {
  enum E { z = 16 };
  int b[X::z];      // OK
};

——尾注]

然后提出的决议:

在 14.6.4.1 [temp.point] 第 3 段更改:

实例化点就在封闭模板的实例化点之前。否则,这种特化的实例化点紧接在引用特化的命名空间范围声明或定义之前。

至:

实例化点与封闭模板的实例化点相同。否则,这种特化的实例化点就在 最近的封闭声明之前。[注意:实例化点仍在命名空间范围内,但在实例化点之前的任何声明,即使不在命名空间范围内,也被视为已看到。]

添加以下第 3 段:

如果隐式实例化的类模板特化、类成员特化或类模板的特化引用包含直接或间接导致实例化的特化引用的类、类模板特化、类成员特化或类模板的特化,则要求类引用的完整性和排序在专业化引用的上下文中应用。

截至最新的草案,非模板案例过去和现在仍然有效。模板案例不是。但是缺陷是草稿,这意味着模板案例旨在编译。

起草:工作组已达成非正式共识,并在暂定决议中进行了粗略描述,但尚无更改的准确措辞。

于 2016-06-10T08:22:53.430 回答