我感到非常惊讶的是,在 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++ 聊天中提到的参考资料):
标准表示执行模板实例化after翻译单元已经被翻译,因此模板实例化会及时发生after所有非模板化元素都已被处理。 2.2 翻译阶段对此进行了描述:
第 1-6 段定义了预处理器的工作和基本信息textual操作(字符集转换、文字串联……)
7/ 分隔标记的空白字符不再重要。每个预处理标记都会转换为一个标记。 (2.7)。对生成的标记进行句法和语义分析,并将其翻译为翻译单元。
8/ 已翻译的翻译单元和实例化单元按如下方式组合:检查每个已翻译的翻译单元以生成所需实例化的列表。找到所需模板的定义。包含这些定义的翻译单元的源是否需要可用是由实现定义的。执行所有必需的实例化以生成实例化单元。 [ 注意:这些与已翻译的翻译单元类似,但不包含对未实例化模板的引用,也不包含模板定义。 — 尾注] 如果任何实例化失败,则程序格式错误。
为了简洁起见,我删除了一些注释。现在,重要的一点似乎是代码的翻译不会在一步中触发模板实例化,然后在后面的步骤中实例化模板。这反过来意味着如果类型是complete在翻译单元中的任何位置,它都会在编译器到达实例化时已被处理。
免责声明:对于我尝试过显示完全相同行为的所有编译器(gcc、clang、comeau、VS 2010)来说,这似乎是一个很好的理由,但这仅表明when在执行实例化时,它没有明确声明该类型在模板实例化时可能不完整。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)