std::is_same 尚未 defined/declared class

std::is_same for a not yet defined/declared class

下面的代码是 gcc 错误吗? 检查 T 类型是否尚未定义 class 圆,returns false。

#include <iostream>

using namespace std;

// uncomment to work
//struct Circle;

struct T_traits
{
    template<typename T>
    constexpr static id() { return is_same<T, class Circle>(); }
};


struct Circle{};

int main()
{
    cout << T_traits::id<Circle>() << "\r\n";
    return 0;
}
return is_same<T, class Circle>();

当您注释掉全局声明时,这实际上会声明一个名为 Circle 的局部 class。 [basic.lookup.elab]/2:

If the elaborated-type-specifier has no nested-name-specifier, and unless the elaborated-type-specifier appears in a declaration with the following form:

     class-key attribute-specifier-seqopt identifier ;

the identifier is looked up according to 3.4.1 but ignoring any non-type names that have been declared.[..]
If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name [..] the elaborated-type-specifier is a declaration that introduces the class-name as described in 3.3.2.

查找是§3.4.1 中定义的简单非限定名称查找。查找是在 T_traits 的定义上下文中完成的,因为我们不处理依赖的东西,因此从不考虑 main 之前的 Circle 声明。
§3.3.2/7(别名 [basic.scope.pdecl]/7):

The point of declaration of a class first declared in an elaborated-type-specifier is as follows:

  • for an elaborated-type-specifier of the form

         class-key identifier

    if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration. [ Note: These rules also apply within templates. — end note ]

但是,删除 class 关键字也不起作用 - 如前所述,标识符不相关,因此在定义上下文中查找。如果此查找未找到任何声明,则编译器必须发出诊断 - 即使没有实例化专门化。