模板的实例化点 class

Point of instantiation of a template class

该代码可以编译吗?

#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;
}

TMPL 根据标准 14.6.4.1/4

在 CL class 定义之前立即实例化

For a class template specialization, ..., if the specialization is implicitly instantiated because it is referenced from within another template specialization, .... Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.

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

您的示例与 defect report. In the defect report, CL is a class template. However the intent of the proposed resolution is to make the template case the same as the non-template one, aka [basic.scope.pdecl] 中的示例不同:

6 After the point of declaration of a class member, the member name can be looked up in the scope of its class. [ Note: this is true even if the class is an incomplete class. For example,

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

end note ]

那么建议的决议:

In 14.6.4.1 [temp.point] paragraph 3 change:

the point of instantiation is immediately before the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.

To:

the point of instantiation is the same as the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the nearest enclosing declaration. [Note: The point of instantiation is still at namespace scope but any declarations preceding the point of instantiation, even if not at namespace scope, are considered to have been seen.]

Add following paragraph 3:

If an implicitly instantiated class template specialization, class member specialization, or specialization of a class template references a class, class template specialization, class member specialization, or specialization of a class template containing a specialization reference that directly or indirectly caused the instantiation, the requirements of completeness and ordering of the class reference are applied in the context of the specialization reference.

As of the latest draft, the non-template case was and is still valid. The template case is not. However the defect is drafting,这意味着模板案例是为了编译。

Drafting: Informal consensus has been reached in the working group and is described in rough terms in a Tentative Resolution, although precise wording for the change is not yet available.