【问题标题】:Templates compilation: gcc vs VS2010模板编译:gcc vs VS2010
【发布时间】:2012-04-25 21:20:21
【问题描述】:

摘自本书 - C++ 模板:David, Nicolai 的完整指南

因此,模板被编译两次:

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

保持第一点,我写了-

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++ 标准?即使没有模板实例化,模板代码是否也必须编译?

【问题讨论】:

  • VC++ 没有实现两阶段名称查找。从来没有,可能在很长时间(如果有的话)都不会。
  • 我很高兴他们在宽大方面犯了错误。
  • @Seth :我不是——这让编写跨平台代码变得更加困难,因为在您使用更兼容的编译器编译代码之前,您不会看到错误。
  • @ildjarn 仅当您从未实例化模板时。此外......只需在更兼容的编译器上测试它。
  • @Seth : 不,还有其他副作用,例如无法识别依赖类型,因此 VC++ 可以让您摆脱很多缺失的 templatetypename 关键字兼容的编译器没有。并且在更合规的编译器上进行测试当然是不切实际的(Windows 上的 Clang 还不是很漂亮),尽管目前是必要的。

标签: c++ visual-studio-2010 templates visual-c++ gcc


【解决方案1】:

有问题的程序格式不正确,但 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
    }
};

结束示例]

【讨论】:

    【解决方案2】:

    您正在看的这本书似乎(主要)反映了作者对编译器实际工作方式的观察,而不是标准的要求。该标准并没有对模板中的格式错误的代码给予额外的宽大处理,只是因为它没有被实例化。

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

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

    【讨论】:

      猜你喜欢
      • 2014-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多