我很惊讶在 g++ 的各种采样版本上,以下编译没有错误或警告:
// Adapted from boost::checked_delete()
template <class T> inline void assert_complete()
{
typedef char type_must_be_complete[ sizeof(T) ? 1 : -1 ];
(void) sizeof(type_must_be_complete);
}
class X;
void f()
{
assert_complete<X>();
}
class X {};
int main() {}
如果 X
的定义丢失或在不同的翻译单元中,我会得到错误。
但是在上面的程序中,f
的定义不就是我的模板的单一实例化点吗? X
在那个实例化点的不完整性难道不是语义错误吗?
(C++03 和/或 C++11 草案)标准是否将此程序称为格式正确、格式错误、格式错误但不需要诊断或未定义行为?
编辑:@David Rodriguez - dribeas 报告说 clang++、comeau 和 Visual Studio 2010 也接受类似的代码。
最佳答案
(我一直在等待 Alf Steinbach 发布答案,但由于他没有这样做,我将发布他在 Lounge C++ 聊天中提到的引用):
标准表明模板实例化是在在翻译单元已经被翻译之后执行的,因此模板实例化及时发生在所有非模板化元素已经完成之后被处理。这在 2.2 翻译阶段中有所描述:
第 1-6 段定义了预处理器的工作和基本的文本操作(字符集的转换、文字的连接......)
7/ White-space characters separating tokens are no longer significant. Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit.
8/ Translated translation units and instantiation units are combined as follows: Each translated translation unit is examined to produce a list of required instantiations. The definitions of the required templates are located. It is implementation-defined whether the source of the translation units containing these definitions is required to be available. All the required instantiations are performed to produce instantiation units. [ Note: These are similar to translated translation units, but contain no references to uninstantiated templates and no template definitions. — end note ] The program is ill-formed if any instantiation fails.
为简洁起见,我删除了一些注释。现在重要的一点似乎是在一步中翻译代码而不触发模板实例化,然后在后面的步骤中实例化模板。这反过来意味着,如果类型在翻译单元中的任何位置是complete,那么在编译器进行实例化时它就已经被处理了。
免责声明:这似乎是我尝试过的所有编译器都表现出完全相同行为的一个很好的理由(gcc、clang、comeau、VS 2010),但这只是说明 当及时执行实例化时,它没有明确说明在模板实例化时类型可能是不完整的。
关于c++ - 模板中的类使用不完整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7210286/