Uses typeid for type of declared type undefined?

I read 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 fully defined, does this 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 '

+7
source share
3 answers

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' 

This is consistent with my interpretation of the standard that you cannot apply typeid to an incomplete type - and a_ref_foo is of an incomplete type, since the full definition of the type foo not displayed. main.cpp (with lines added) is poorly formed and requires diagnostics.

Update:

I reproduced this problem using Visual Studio 2010 Express. Even with language extensions disabled, this trivial program:

 #include <typeinfo> struct foo; int main() { typeid (foo); return 0; } 

compiled without 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 the type of the class, the class must be fully defined.

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

Looks like a bug in Visual Studio. (If anyone wants to report this to Microsoft, continue.)

+10
source

Yes, the program is poorly formed (and does not cause undefined behavior).

If you're wondering why, then you should consider that typeid is one 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 give a reference to the type_info object for the actual type (in this case, bar ), and if the type does not have any virtual function, then it will return a reference to the type_info object for static type of expression (in this case foo ).

In order for the compiler to generate the appropriate code, the compiler must know in the place where typeid used which of these two cases applies. If the type is incomplete, this information is not available to the compiler.

+5
source

Your program is completely correct, because the get_some_foo and bar functions are global. So, bar fully defined, but if you define the variant bar in main.cpp , then use it as a parameter in typeid, or an error occurs during compilation.

0
source

All Articles