在前向声明类型未定义的行为上使用typeid?

Zac*_*Zac 10 c++ standards c++11

我是否正确读取标准5.2.8.3: ... If the type of the expression is a class type, the class shall be completely-defined. 如果类型不是"完全定义",那是否意味着以下程序未定义?

Foo.cpp中:

struct foo
{
  virtual void a(){}
};

struct bar : foo
{
  virtual void a(){}
};

bar abar;

foo& get_some_foo()
{
  return abar;
}
Run Code Online (Sandbox Code Playgroud)

main.cpp中:

#include <iostream>
#include <typeinfo>

struct foo;

foo& get_some_foo();

int main()
{
  foo& a_ref_foo(get_some_foo());

  std::cout << "a_ref_foo typeid name: " << typeid(a_ref_foo).name() << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

MSVC10输出:`a_ref_foo typeid name:struct foo'

Kei*_*son 13

当我用以下代码编译代码时:

g++ foo.cpp main.cpp -o main
Run Code Online (Sandbox Code Playgroud)

我明白了:

main.cpp: In function ‘int main()’:
main.cpp:12:52: error: invalid use of incomplete type ‘struct foo’
main.cpp:4:8: error: forward declaration of ‘struct foo’
Run Code Online (Sandbox Code Playgroud)

这与我对标准的解释一致,即你不能应用于typeid不完整的类型 - 并且a_ref_foo是不完整的类型,因为类型的完整定义foo是不可见的.main.cpp(我添加的线条)格式不正确,需要进行诊断.

更新:

我已经使用Visual Studio 2010 Express重现了这个问题.即使禁用语言扩展,这个简单的程序:

#include <typeinfo>

struct foo;

int main()
{
  typeid (foo);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译时没有诊断消息.使用gcc 4.7,我得到:

main.cpp: In function ‘int main()’:
main.cpp:7:14: error: invalid use of incomplete type ‘struct foo’
main.cpp:3:8: error: forward declaration of ‘struct foo’
Run Code Online (Sandbox Code Playgroud)

同样的规则:

如果表达式的类型是类类型,则应完全定义类.

出现在ISO,C++标准的1998年,2003年和2012年版本中.

看起来像Visual Studio中的错误.(如果有人想向微软报告,请继续.)

  • 在这种情况下,使用"shall"意味着它是不正确的,因为这是一个可诊断的规则(即,它不是说"不需要诊断"并且没有明确地描述为未定义的行为). (4认同)

Dav*_*eas 8

是的,程序格式不正确(而不是导致未定义的行为).

如果你想知道为什么,那么你应该考虑这typeid是一个单一的运算符,但它对于多态类型的语义与非多态类型完全不同.特别是,如果foo是多态的(至少有一个虚函数,那么typeid将产生type_info实际类型的对象的引用(在这种情况下bar),而如果该类型没有任何虚函数,那么它将返回对该type_info对象的引用对于表达式的静态类型(在本例中foo).

为了使编译器生成适当的代码,编译器必须知道typeid哪个地方使用了两种情况中的哪一种.如果类型不完整,则编译器不存在该信息.