将源代码从Visual C ++移植到GCC有什么缺陷

时间:2014-08-26 22:55:14

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

众所周知,GCC比Visual C ++更严格地实现C ++标准。 坦率地说,Visual C ++并不能很好地遵循C ++标准。

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

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

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

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

建议的问题描述格式:

  • 代码段(使用Visual C ++编译好)
  • GCC错误或产生警告
  • 两个编译器版本都要重现
  • 参考违反的C ++标准声明(可选,可以在以后添加)
  • 解决方案(如何更改代码以便VC ++和GCC成功编译)

2 个答案:

答案 0 :(得分:3)

这是一个非常广泛的问题,但这里有一些我遇到过的事情:

声明错误点:

#include <iostream>

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

int s;

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

输出应该是&#34;正确&#34;,但Visual Studio的(所有版本)输出是&#34;不正确&#34;。


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

#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的输出是&#34;不正确&#34;。


两阶段名称查询:

#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);
}

输出应该是&#34;更正&#34;,但Visual Studio(目前为止所有版本)的输出是&#34;不正确&#34;。


替代标记不起作用:

int main() <% %>

此程序应该编译并运行,但没有Visual Studio版本成功编译它。


for-loop initializer子句中的用户定义类型定义:

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

  }
}

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


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

答案 1 :(得分:1)

使用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> {};