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
关键字也不起作用 - 如前所述,标识符不相关,因此在定义上下文中查找。如果此查找未找到任何声明,则编译器必须发出诊断 - 即使没有实例化专门化。
下面的代码是 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
关键字也不起作用 - 如前所述,标识符不相关,因此在定义上下文中查找。如果此查找未找到任何声明,则编译器必须发出诊断 - 即使没有实例化专门化。