将源代码从 Visual C++ 移植到 GCC 都有哪些陷阱[关闭]

Posted

技术标签:

【中文标题】将源代码从 Visual C++ 移植到 GCC 都有哪些陷阱[关闭]【英文标题】: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 格式正确回答的问题不在主题范围内。您要求发布数十个甚至数百个答案,但没有一个答案是正确的。 【参考方案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> ;

【讨论】:

以上是关于将源代码从 Visual C++ 移植到 GCC 都有哪些陷阱[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 将 C++ 代码从 Visual Studio 移植到 Linux Eclipse IDE 时出现问题

将 Visual C++ 项目移植到 C# [关闭]

Visual C 的 strdupa() 实现

将 Visual Studio C++ 移植到 Linux

从 gcc 3.3.3 到 4.1.0 的移植,C++ 模板,未定义的引用

将 GNU C++ 程序移植到 Visual C++