来自书籍 - C ++模板:David,Nicolai的完整指南
因此,模板被编译两次:
- 在没有实例化的情况下,检查模板代码本身的语法是否正确。发现语法错误,例如丢失 分号。
- 在实例化时,检查模板代码以确保所有调用都有效。发现无效的呼叫,例如 不支持的函数调用。
醇>
保持第一点,我写道 -
template<typename T>
void foo( T x)
{
some illegal text
}
int main()
{
return 0;
}
它在Visual Studio 2010上构建正常,没有关闭优化的任何警告。但是,it failed on gcc-4.3.4。哪一个符合C ++标准?即使没有模板实例化,模板代码也必须编译吗?
答案 0 :(得分:7)
有问题的程序格式不正确,但C ++标准在这种情况下不需要诊断,因此Visual Studio和GCC都以兼容的方式运行。从C ++ 03标准的§14.6/ 7(强调我的):
知道哪些名称是类型名称允许检查每个模板定义的语法。没有 应为可以生成有效特化的模板定义发出诊断。 如果没有 可以为模板定义生成有效的专门化,并且不对该模板进行实例化,即模板 定义格式错误,无需诊断。如果非依赖名称中使用的类型不完整 在定义模板但在完成实例化的时刻完成的点,和 如果该类型的完整性影响程序是否格式正确或影响语义 该计划的程序不正确;无需诊断。 [注意:如果实例化模板, 错误将根据本标准中的其他规则进行诊断。确切地说,这些错误被诊断出来了 是一个实施质量问题。 ] [示例:
int j; template<class T> class X { // ... void f(T t, int i, char* p) { t = i; // diagnosed if X::f is instantiated // and the assignment to t is an error p = i; // may be diagnosed even if X::f is // not instantiated p = j; // may be diagnosed even if X::f is // not instantiated } void g(T t) { +; //may be diagnosed even if X::g is // not instantiated } };
- 结束示例]
答案 1 :(得分:0)
您正在查看的这本书似乎(主要)反映了作者关于编译器如何真正起作用的观察,而不是标准的要求。标准对于编译器对模板内部格式错误的代码给予额外的宽容并没有多大的帮助,只是因为它没有实例化。
与此同时,本书是正确的,在编译实例化之前,编译器确实无法做很多事情。例如,您可以使用依赖名称作为函数的名称(或者像函数一样调用它 - 无论如何 - 如果它是仿函数,那么它也会很好)。如果你在 一个函数的类上实例化该模板,那很好。如果你在一个真正为int
的类上实例化它,试图调用它无疑会失败。在你实例化它之前,编译器无法分辨哪个是哪个。
这是concepts
真正打算添加到C ++中的很大一部分。您可以直接指定(例如)模板X将像函数一样调用T::y
。然后编译器可以将模板的内容与概念中的声明进行比较,并确定模板的主体是否符合概念中的声明。在另一个方向,编译器只需要将类(或其他)与概念进行比较,以确定实例化该模板是否有效。如果它不起作用,它可以直接报告错误作为违反相关概念(因为它现在,它试图实例化模板,并且你经常得到一些奇怪的错误信息,表明真正的问题很糟糕,如果有的话。)