【问题标题】:What are pitfalls of porting source code from Visual C++ to GCC [closed]将源代码从 Visual C++ 移植到 GCC 有哪些陷阱[关闭]
【发布时间】:2014-08-26 22:55:13
【问题描述】:

众所周知,GCC 对 C++ 标准的实现比 Visual C++ 严格得多。 坦率地说,Visual C++ 只是没有很好地遵循 C++ 标准。

对于主要使用 Visual C++ 进行开发但需要至少使用 GCC 进行代码可移植和编译的开发人员来说,这一直是令人头疼的问题。

一些 Visual C++ 语言不当行为记录在 MSDN Nonstandard Behavior topic 中,实际上还有很多其他未记录的案例。

这篇文章的目的是记录所有已知的 VC++ 与 GCC(最流行的 C++ 编译器)的兼容性问题。当某些代码 sn-p 使用 Visual C++ 编译而没有警告(W4 级别)并且不使用 GCC(产生错误或警告)时,会引发问题。

请注意,它仅适用于标准 C++ 问题,__super__forceinline 等 Microsoft 特定语言扩展超出范围。

问题描述的建议格式:

  • 代码 sn-p(使用 Visual C++ 编译成功)
  • GCC 错误或它产生的警告
  • 要重现的两个编译器版本
  • 对违反 C++ 标准语句的引用(可选,以后可以添加)
  • 解决方案(如何更改代码以使 VC++ 和 GCC 都成功编译)

【问题讨论】:

  • 坚持使用标准 C++,您很可能会避免这些陷阱。
  • @40two 即使坚持标准 C++ 也不会很好地工作。正如 OP 所说,Visual Studio 在遵循标准方面真的很糟糕,并且创建适用于两者的代码是实际标准的受限集。那或一堆'#ifdef MSVC'
  • @Smith_61 请注意我的陈述中的“最可能”一词。
  • 这个问题太宽泛了,不适合 SO。为了得到完整的回答,需要为每个不符合标准的功能发布代码 sn-ps 和由此产生的错误消息以及替代解决方案。需要一个完整的网站或 wiki 来解决这个主题。
  • 无法以 Stack Overflow 格式正确回答的问题不在主题范围内。您要求发布数十个甚至数百个答案,但没有一个答案是正确的。

标签: c++ visual-c++ gcc portability


【解决方案1】:

这是一个相当广泛的问题,但我遇到了一些问题:

声明点错误:

#include <iostream>

struct S {
  S(int) { std::cout << "Incorrect\n"; }
  S(S const &) { std::cout << "Correct\n"; }
};

int s;

int main() {
  S s(s);
}

输出应该是“正确的”,但 Visual Studio(所有版本)的输出是“不正确的”。


复制分配和复制初始化的生成不正确:

#include <iostream>

struct B {
    B &operator = (B &) { std::cout << "Correct\n"; return *this; }
    template<typename T>
    B &operator = (T &) { std::cout << "Incorrect\n"; return *this; }
};

struct D : B {};

int main() {
    D d;
    d = d;
}

我认为这已在 Visual Studio 2012 中修复。在 2012 年之前 VS 的输出是“不正确的”。


两阶段名称查找:

#include <iostream>

static void foo(long) {
  std::cout << "Correct\n";
}

template<typename T>
void bar(T t) {
  foo(t);
}

static void foo(int) {
  std::cout << "Incorrect\n";
}

int main() {
  bar(1);
}

输出应该是“正确的”,但 Visual Studio(到目前为止的所有版本)的输出是“不正确的”。


替代令牌不起作用:

int main() <% %>

该程序应该可以编译并运行,但没有任何版本的 Visual Studio 可以成功编译它。


for-loop 初始化子句中用户定义的类型定义:

int main() {
  for (struct {int a;} a = {0}; a.a < 10; ++(a.a)) {

  }
}

这是合法的,但 VS 不允许。


所有这些都在 gcc 和 clang 下正确编译和运行,可以追溯到很多版本。 Gcc 曾经有两阶段查找的问题,但现在没有了。

【讨论】:

    【解决方案2】:

    代码 sn-p,用 VC++ 2013 编译成功:

    struct X
    {
       template <class T> struct Z {};
    
       template <> struct Z<int> {}; // Source of problem
    };
    

    产生 GCC 错误 (4.7.2): error: explicit specialization in non-namespace scope

    违反标准条款: 14.7.3 Explicit specialization, p.2 - An explicit specialization shall be declared in a namespace enclosing the specialized template.

    解决方案:使用部分特化代替显式特化:

    struct X
    {
        template <class T, class MakeItPartial=void> struct Z {};
    
        template <class MakeItPartial> struct Z<int, MakeItPartial> {};
    };
    

    或者如果可能的话,把它移到封闭的命名空间范围内:

    struct X
    {
        template <class T> struct Z {};
    };
    
    template <> struct X::Z<int> {};
    

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 2012-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 2010-10-16
      • 1970-01-01
      相关资源
      最近更新 更多