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++_Templates_Forward Declaration - Fatal编程技术网

C++ 当包装到模板中时,不完整类型的新文件将编译

C++ 当包装到模板中时,不完整类型的新文件将编译,c++,templates,forward-declaration,C++,Templates,Forward Declaration,考虑这段代码,其中有一个明显的编译错误:(1) 使用唯一\u ptr也不会有任何帮助:(2) 我认为它与模板s有关,事实上:在模板中包装新的,编译:(5) 这是怎么回事?据我所知,编译器必须知道A的大小/定义才能分配它,因此仅仅声明它是不够的。此外,我认为定义必须在分配之前 当直接使用new时,这似乎是正确的(1,4)。但是当new被包装时,很明显我错了(2,3,5,6) 到目前为止,我发现的可能解释如下: 对已完成类型的检查延迟到模板实例化发生。我认为这是正确的,但在我的例子中,直接使用ne

考虑这段代码,其中有一个明显的编译错误:(1)

使用
唯一\u ptr
也不会有任何帮助:(2)

我认为它与
模板
s有关,事实上:在
模板
中包装
新的
,编译:(5)

这是怎么回事?据我所知,编译器必须知道
A
的大小/定义才能分配它,因此仅仅声明它是不够的。此外,我认为定义必须在分配之前

当直接使用
new
时,这似乎是正确的(1,4)。但是当
new
被包装时,很明显我错了(2,3,5,6)

到目前为止,我发现的可能解释如下:

  • 对已完成类型的检查延迟到
    模板
    实例化发生。我认为这是正确的,但在我的例子中,直接使用
    newa()
    和调用
    my_new()
    几乎发生在同一位置。所以这不可能是原因。对吧?
  • 使用不完整的类型作为
    模板
    参数可能是未定义的行为。这是真的吗?即使启用所有警告,编译器也不会抱怨。同样,比较5和6似乎表明,编译器足够聪明,能够理解以下定义(从而实际上使类型完整)
为什么4被认为是不正确的,而5编译(或者5只是错误地编译了未定义的行为[但是3也必须有缺陷,对吗?])


顺便说一句:使用clang++-3.5.0和g++-4.9.2测试[temp.point]/p1,8,强调:

1对于函数模板专用化,成员函数模板 专门化,或成员函数或静态函数的专门化 类模板的数据成员,如果专门化是隐式的 已实例化,因为它是从另一个模板中引用的 专门化及其引用所依赖的上下文 模板参数,专门化的实例化点 是封闭专门化的实例化点。 否则,这种专门化的实例化点 紧跟在 指专业化。

8函数模板、成员函数模板的专门化, 或类模板的成员函数或静态数据成员的 在翻译单元内有多个实例化点,以及 除了上述实例化点之外,对于任何 这种专门化在 翻译单元,翻译单元的末尾也被视为 实例化点。类模板的专门化至少具有 大多数情况下,在翻译单元中只有一个实例化点。A. 任何模板的专门化都可能在 多个翻译单元如果两个不同的实例化点 根据一个模板给出不同的含义 定义规则(3.2),程序格式错误,无诊断 必需。


my_new
有两个实例化点,一个在
B
定义的末尾,另一个在翻译单元的末尾。由于这两点将产生不同的含义(对于代码段3和5),因此程序是格式错误的NDR(即,它具有未定义的行为)。

§14.6.4.1[临时点]/p1,8,重点:

1对于函数模板专用化,成员函数模板 专门化,或成员函数或静态函数的专门化 类模板的数据成员,如果专门化是隐式的 已实例化,因为它是从另一个模板中引用的 专门化及其引用所依赖的上下文 模板参数,专门化的实例化点 是封闭专门化的实例化点。 否则,这种专门化的实例化点 紧跟在 指专业化。

8函数模板、成员函数模板的专门化, 或类模板的成员函数或静态数据成员的 在翻译单元内有多个实例化点,以及 除了上述实例化点之外,对于任何 这种专门化在 翻译单元,翻译单元的末尾也被视为 实例化点。类模板的专门化至少具有 大多数情况下,在翻译单元中只有一个实例化点。A. 任何模板的专门化都可能在 多个翻译单元如果两个不同的实例化点 根据一个模板给出不同的含义 定义规则(3.2),程序格式错误,无诊断 必需。


my_new
有两个实例化点,一个在
B
定义的末尾,另一个在翻译单元的末尾。由于这两点将导致不同的含义(对于代码片段3和5),因此程序是格式错误的NDR(即,它有未定义的行为)。

如果不清楚,因为那篇文章只讨论了两阶段名称查找的更严格的方面,模板名称在代码的另一个阶段之前不会实例化,在它已经阅读并阅读了
A
的定义之后,这就是它编译的原因。将模板实例化延迟到翻译单元结束是一种常见的实现技术。你的代码
struct A;
struct B {
  B() { new A(); } // error: allocation of incomplete type 'A'
};
struct A;
struct B {
  B() { std::make_unique<A>(); } // error: due to ~unique_ptr()
};
struct A;
struct B {
  B() { std::make_unique<A>(); }
};
struct A {}; // OK, when a definition is added **below**
struct A;
struct B {
  B() { new A(); } // error: allocation of incomplete type 'A'
};
struct A {};
template <typename T> 
T* my_new() { return new T(); } // OK, when wrapped in template
struct A;
struct B {
  B() { my_new<A>(); }
};
struct A {};
template <typename T> 
T* my_new() { return new T(); } // error: allocation of incomplete type 'A'
struct A;
struct B {
  B() { my_new<A>(); }
}; 
// do note: definition of A removed