模板编译:gcc vs VS2010

Templates compilation: gcc vs VS2010

本文关键字:vs VS2010 gcc 编译      更新时间:2023-10-16

摘自书 - C++模板:大卫,尼古拉的完整指南

因此,模板被编译两次:

  1. 如果不进行实例化,则会检查模板代码本身的语法是否正确。发现语法错误,例如缺少 分号。
  2. 在实例化时,将检查模板代码以确保所有调用都有效。发现无效调用,例如 不支持的函数调用。

保留第一点,我写道——

template<typename T>
void foo( T x)
{
   some illegal text
}
int main()
{
   return 0;
}

它在Visual Studio 2010上构建良好,没有任何关闭优化的警告。无论如何,它在 gcc-4.3.4 上失败了。哪一个符合C++标准?即使没有模板实例化,模板代码是否也必须编译?

有问题的程序格式不正确,但在这种情况下,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
    }
};

结束示例]

你正在看的这本书似乎反映了(大部分)作者对编译器如何真正工作的观察,而不是标准的要求。该标准并没有真正说明编译器对模板内格式错误的代码的额外宽容,只是因为它没有实例化。

同时,这本书是正确的,编译器在实例化之前确实无法做很多事情来检查。例如,您可以使用依赖名称作为函数的名称(或者像函数一样调用它 - 如果它是函子,那也没问题)。如果你在一个类上实例化该模板,它是一个函数,很好。如果你在一个它真的是一个int的类上实例化它,试图调用它无疑会失败。在你实例化它之前,编译器无法分辨哪个是哪个。

这是concepts真正打算添加到C++中的很大一部分。您可以直接指定(例如)模板 X 将像函数一样调用T::y。然后,编译器可以将模板的内容与概念中的声明进行比较,并确定模板的主体是否适合概念中的声明。在另一个方向上,编译器只需要将类(或其他任何)与概念进行比较,以确定实例化该模板是否有效。如果它不起作用,它可以直接将错误报告为违反相关概念(就像现在一样,它尝试实例化模板,并且您经常收到一些奇怪的错误消息,指示真正的问题很差,如果有的话)。