我是否在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;
}
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输出:`a_ref_foo typeid name:struct foo'
答案 0 :(得分:13)
当我使用以下代码编译代码时
g++ foo.cpp main.cpp -o main
我明白了:
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’
这与我对标准的解释一致,即你不能将typeid
应用于不完整的类型 - 而a_ref_foo
属于不完整类型,因为{{1}类型的完整定义是不可见的。 foo
(加上我添加的行)格式不正确,需要进行诊断。
更新:
我已经使用Visual Studio 2010 Express重现了这个问题。即使禁用语言扩展,这个简单的程序:
main.cpp
编译时没有诊断消息。使用gcc 4.7,我得到:
#include <typeinfo>
struct foo;
int main()
{
typeid (foo);
return 0;
}
同样的规则:
如果表达式的类型是类类型,则类应为 完全定义
出现在ISO,C ++标准的1998年,2003年和2012年版本中。
看起来像Visual Studio中的错误。 (如果有人想向微软报告,请继续。)
答案 1 :(得分:8)
是的,该程序格式不正确(而不是导致未定义的行为)。
如果您想知道为什么,那么您应该考虑typeid
是单个运算符,但它对于多态类型的语义与非多态类型完全不同。特别是,如果foo
是多态的(至少有一个虚函数,那么typeid
将产生对实际类型的type_info
对象的引用(在这种情况bar
),如果类型没有任何虚函数,那么它将返回对表达式的 static 类型的type_info
对象的引用(在这种情况下) foo
)。
为了使编译器生成适当的代码,编译器必须知道在使用typeid
的地方,这两种情况中的哪一种适用。如果类型不完整,则编译器不会显示该信息。
答案 2 :(得分:0)
您的程序完全正确,因为函数get_some_foo
和bar
是全局变量。因此,bar
已完全定义,但如果您在bar
中定义main.cpp
的变体,则将其用作typeid中的参数,否则在编译时会发生错误。