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'
typeid is an operator in C++. It is used where the dynamic type or runtime type information of an object is needed. It is included in the <typeinfo> library. Hence inorder to use typeid, this library should be included in the program.
A forward declaration is not so much dangerous in itself, but it is a code smell. If you need a forward declaration, it means two classes are tightly coupled, which usually is bad. Thus it is an indication that your code may need refactoring.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With