简体   繁体   中英

Is using typeid on a forward declared type undefined behavior?

Am I reading the standard correctly in 5.2.8.3: ... If the type of the expression is a class type, the class shall be completely-defined. If the type is not "completely-defined" does that mean the following program is undefined?

foo.cpp:

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

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

bar abar;

foo& get_some_foo()
{
  return abar;
}

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;
}

MSVC10 outputs: `a_ref_foo typeid name: struct foo'

When I compile your code with:

g++ foo.cpp main.cpp -o main

I get:

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’

That agrees with my interpretation of the standard, that you can't apply typeid to an incomplete type — and a_ref_foo is of an incomplete type, since the full definition of the type foo is not visible. main.cpp (with the lines I added) is ill-formed, and a diagnostic is required.

Update :

I've reproduced the issue with Visual Studio 2010 Express. Even with language extensions disabled, this trivial program:

#include <typeinfo>

struct foo;

int main()
{
  typeid (foo);
  return 0;
}

compiled with no diagnostic messages. With gcc 4.7, I get:

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’

The same rule:

If the type of the expression is a class type, the class shall be completely-defined.

appears in the 1998, 2003, and 2012 versions of the ISO C++ standard.

Looks like a bug in Visual Studio. (If somebody would like to report this to Microsoft, go ahead.)

Yes, the program is ill-formed (rather than causing undefined behavior).

If you wonder why , then you should consider that typeid is a single operator, but it has completely different semantics for polymorphic types than for non-polymorphic types. In particular, if foo is polymorphic (has at least one virtual function, then typeid will yield a reference to the type_info object for the actual type (in this case bar ) while if the type does not have any virtual function then it will return a reference to the type_info object for the static type of the expression (in this case foo ).

For the compiler to generate the appropriate code, the compiler must know at the place where typeid is used which of the two cases applies. If the type is incomplete, that information is not present for the compiler.

Your program is completely correct because functions get_some_foo and bar are globals. So bar is completely defined, but if you define a variant of bar in main.cpp , then use it as a parameter in typeid , or error occurs when compiling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM