C++;模板实例化混淆点 我对C++中实例化的点有点困惑。考虑下面的代码(它在VC++ 2012下编译精细): structfoo; 模板Foo*Create(){return new Foo;} Foo*MyFoo=Create(); //(A)我期望实例化点在这里 结构Foo{}; //(B)但它似乎在这里
我希望实例化点是上面的(A)点,但显然不是这样(因为Foo在(A)点是一个不完整的类型)。有人能解释一下为什么会这样编译吗?这是MSVC的标准行为还是怪癖C++;模板实例化混淆点 我对C++中实例化的点有点困惑。考虑下面的代码(它在VC++ 2012下编译精细): structfoo; 模板Foo*Create(){return new Foo;} Foo*MyFoo=Create(); //(A)我期望实例化点在这里 结构Foo{}; //(B)但它似乎在这里,c++,templates,C++,Templates,我希望实例化点是上面的(A)点,但显然不是这样(因为Foo在(A)点是一个不完整的类型)。有人能解释一下为什么会这样编译吗?这是MSVC的标准行为还是怪癖 编辑:澄清一下,我真正想知道的是:这是不是一个有效的程序?编译器是否应该接受它?为什么?(很明显,如果编译器接受了该程序,但它不应该接受,那么这是MSVC的不一致行为。)让我们从顶部开始。Create()的定义无效,因为它试图为正文中的不完整类型分配内存。但是,您可以在这里声明此函数,并在以后定义它 Create()的声明很好——允许声明指向
编辑:澄清一下,我真正想知道的是:这是不是一个有效的程序?编译器是否应该接受它?为什么?(很明显,如果编译器接受了该程序,但它不应该接受,那么这是MSVC的不一致行为。)让我们从顶部开始。
Create()
的定义无效,因为它试图为正文中的不完整类型分配内存。但是,您可以在这里声明此函数,并在以后定义它
Create()
的声明很好——允许声明指向不完整类型的指针或返回不完整类型的函数
当然,如果从代码末尾删除Foo的定义,编译器将到达末尾并意识到它从未看到过Foo类型的定义。然后,您的Foo结构不是定义之前的不完整类型,而是未定义的,任何引用它的代码都将无法编译
无效程序(尝试定义分配不完整类型的函数)
structfoo;
模板Foo*Create(){return new Foo;}
Foo*MyFoo=Create();
结构Foo{};
程序的有效版本(将分配Foo的函数定义移到末尾):
structfoo;
模板Foo*Create();
Foo*MyFoo=Create();
结构Foo{};
模板Foo*Create(){return new Foo;}
该程序在g++下编译,据我所知,这是完全允许的。
本标准的相关章节:
5.3.1p1
通过指向不完整类型(cv void除外)的指针进行间接寻址是有效的。由此获得的左值可以以有限的方式使用(例如初始化引用);此左值不能转换为prvalue
8.3.5p9
“类型不应在返回或参数类型中定义。参数类型或函数定义的返回类型不应是不完整的类类型”这看起来像是MSVC不符合查询的另一个影响。。这是一个MVCE。这是演示我所观察到的令人困惑的编译器行为的最小示例。看看这个。它不能在GCC上编译。@PeterRuderman[expr.new]指出
new
表达式中的类型必须是完整的类型,并且Foo
在实例化Create()
的地方是不完整的。因此,我很清楚您的示例的格式是错误的。在定义Create()时不定义Foo是可以的(因为Create是一个模板函数)。但它必须在创建实例化时定义。不,不是有效的程序。代码无效。如果你认为是,你应该提供相关的参考从C++标准来支持你的索赔。你说的对,这不是一个有效的程序,我完全错过了最初的(无效)。函数定义在函数声明之后进行辩护。@chmod_007:使用不完整的类型定义模板函数是完全合法的。类型必须仅在实例化时完成。@Peterderman我认为这只是模板参数的情况(在本例中,T
)。不适用于在其他地方正向声明的不完整类型。在g++下编译的尝试产生:错误:不完整类型“struct Foo”的使用无效
和错误:正向声明“struct Foo”
struct Foo;
template <class T> Foo* Create() { return new Foo; }
Foo* MyFoo = Create<int>();
// (A) I expected point of instantiation to be here
struct Foo {};
// (B) But it appears to be here instead
struct Foo;
template <class T> Foo* Create() { return new Foo; }
Foo* MyFoo = Create<int>();
struct Foo {};
struct Foo;
template <class T> Foo* Create();
Foo* MyFoo = Create<int>();
struct Foo {};
template <class T> Foo* Create() { return new Foo; }