Reputation: 3285
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'
Upvotes: 10
Views: 3441
Reputation: 1
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.
Upvotes: 0
Reputation: 263507
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.)
Upvotes: 13
Reputation: 208426
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.
Upvotes: 8