Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;模板实例化混淆点 我对C++中实例化的点有点困惑。考虑下面的代码(它在VC++ 2012下编译精细): structfoo; 模板Foo*Create(){return new Foo;} Foo*MyFoo=Create(); //(A)我期望实例化点在这里 结构Foo{}; //(B)但它似乎在这里_C++_Templates - Fatal编程技术网

C++;模板实例化混淆点 我对C++中实例化的点有点困惑。考虑下面的代码(它在VC++ 2012下编译精细): structfoo; 模板Foo*Create(){return new Foo;} Foo*MyFoo=Create(); //(A)我期望实例化点在这里 结构Foo{}; //(B)但它似乎在这里

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()的声明很好——允许声明指向

我希望实例化点是上面的(A)点,但显然不是这样(因为Foo在(A)点是一个不完整的类型)。有人能解释一下为什么会这样编译吗?这是MSVC的标准行为还是怪癖


编辑:澄清一下,我真正想知道的是:这是不是一个有效的程序?编译器是否应该接受它?为什么?(很明显,如果编译器接受了该程序,但它不应该接受,那么这是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; }