以下代码是 gcc bug 吗? 检查 T 类型是否为尚未定义的 Circle 类,返回 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
的本地类。 [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
关键字也不起作用 - 如前所述,标识符不是依赖的,因此会在定义上下文中查找。如果此查找未找到任何声明,则编译器必须发出诊断 - 即使没有实例化专门化。
关于c++ - std::is_same 对于尚未定义/声明的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27890699/