typeid不适用于非静态成员函数

Bel*_*loc 13 c++ typeid language-lawyer c++11

clang不编译typeid下面的第三个调用(参见实例).但我在§5.2.8中看不到任何禁止这一点的内容,特别是当我们认为表达式B::f不是多态类类型的glvalue时(见第3段).此外,根据此段,表达式B::f是未评估的操作数,因此,调用typeid(B::f)应该编译.请注意,GCC不会编译以下任何调用typeid:

#include <iostream>
#include <typeinfo>

struct A{ int i; };
struct B{ int i; void f(); };

int main()
{
    std::cout << typeid(A::i).name() << '\n';
    std::cout << typeid(B::i).name() << '\n';
    std::cout << typeid(B::f).name() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*our 11

据我所知clang,使用非静态成员仅在未评估的上下文中才有效(如果它是数据成员).因此gcc前两种情况看起来不正确,但gcc在情况下正常工作,sizeof并且decltype还有未评估的操作数.

草案C++ 11标准部分5.1.1 [expr.prim.general]:

只能使用表示非静态数据成员或类的非静态成员函数的id表达式:

并包括以下项目:

如果该id-expression表示非静态数据成员,则它出现在未评估的操作数中.[例如:

struct S {
    int m;
};
int i = sizeof(S::m); // OK
int j = sizeof(S::m + 42); // OK 
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

其余的子弹不适用,它们如下:

  • 作为类成员访问(5.2.5)的一部分,其中对象表达式引用成员的类61或从该类派生的类,或者
  • 形成指向成员(5.3.1)的指针,或
  • 在mem-initializer中,用于该类的构造函数或从该类派生的类(12.6.2),或者
  • 用于该类的非静态数据成员或从该类派生的类(12.6.2)的大括号或等于初始化程序,或者

我们知道操作数没有从部分5.2.8说明:

当typeid应用于多态类类型的glvalue以外的表达式时,[...]表达式是未评估的操作数(第5条).

我们可以从语法中看到id-expressionunqualified-idqualified-id:

id-expression:
    unqualified-id
    qualified-id
Run Code Online (Sandbox Code Playgroud)

更新

提交了一个gcc 错误报告:typeid不允许表达非静态数据成员的id表达式.