std :: is_same用于尚未定义/声明的类

时间:2015-01-11 18:42:18

标签: c++ c++14

以下代码是gcc错误吗? 检查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;
}

1 个答案:

答案 0 :(得分:5)

return is_same<T, class Circle>();

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

  

如果 elaborated-type-specifier 没有嵌套名称说明符,   除非 elaborated-type-specifier 出现在声明中   以下形式:

class-key   attribute-specifier-seq opt 标识符 ;

  根据3.4.1查找标识符,但忽略任何非类型   已经宣布的名字。[..]
  如果 class-key 引入 elaborated-type-specifier   并且此查找找不到先前声明的类型名称   [...] elaborated-type-specifier 是一个声明   引入 class-name ,如3.3.2。

中所述

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

  

首先在一个声明中声明一个类的声明    elaborated-type-specifier 如下:

     
      
  • 表格的详细说明类型

         

    类密钥标识符

         

    如果在中使用了 elaborated-type-specifier   在命名空间作用域中定义的函数的 decl-specifier-seq parameter-declaration-clause ,标识符声明为   包含声明的命名空间中的 class-name ; 否则,除了作为朋友声明之外,标识符是在最小的命名空间或包含该范围的块范围中声明的   宣言。 [注意:这些规则也适用于模板。 - 结束   注意]

  •   

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