【问题标题】:Visual Studio 2017: ambiguous symbol size_t in linux projectsVisual Studio 2017:Linux 项目中的模棱两可的符号 size_t
【发布时间】:2017-11-13 01:22:54
【问题描述】:

在 Visual Studio 2017 中创建 Linux 项目并在源代码中插入 using namespace std; 时,如下所示:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    size_t i = 1;
    string s = to_string(i);
    cout << i << s << endl;
    return 0;
}

VS在size_t下划线,表示这是一个模棱两可的符号。

如果我按 F12 (Go to definition),它会为我提供两个定义位置:

来自stddef.h

(C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Linux\include\usr\include\x86_64-linux-gnu\5\include\stddef.h):

// ...
namespace std
{
  typedef __SIZE_TYPE__     size_t;
// ...

还有c++config.h

(C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\Linux\include\usr\include\x86_64-linux-gnu\c++\5\bits\c++config.h):

// ...
#if !(defined (__GNUG__) && defined (size_t))
typedef __SIZE_TYPE__ size_t;
// ...

它只发生在 VS 中的 Linux 项目中,而不是 Windows 项目。

是否有任何已知的解决方案(除了“不要使用using namespace std; :) )?

更新:将此问题报告给 Microsoft:https://developercommunity.visualstudio.com/content/problem/67405/ambiguous-symbol-size-t-in-linux-projects-when-usi.html

Upd2:微软表示他们已修复它,解决方案将在下一次更新中:https://developercommunity.visualstudio.com/content/problem/67405/ambiguous-symbol-size-t-in-linux-projects-when-usi.html

【问题讨论】:

  • @Rakete1111 请不要删除“visual-studio-2017”标签,这个问题只针对这个版本。
  • 所以你的意思是,当你写using namespace std时你只会得到丑陋的曲线?这将使它成为 VS 2017 的最佳新功能。
  • 好吧,靠理智和利益的力量,删除 using namespace std;会给你带来两件事(没有波浪线并修复语句的所有其他问题),关闭智能感知会给你带来一件事(没有波浪线)。从我在 CS 大学学到的所有经济学中,我会说第一个更有利可图;)
  • Linux 头文件中的一个错误导致 itellisense 中出现波浪状的红线你知道 什么Linus 会回答这个问题吗?
  • @n.m.再次仔细阅读:VS 中用于 Linux 项目的标头中的错误。不管怎样,你知道 Linus 会怎么说 C++ 本身吗?

标签: c++ visual-studio-2017


【解决方案1】:

看起来微软和其他编译器在 typedef 输入和输出命名空间方面存在差异。

这个源文件

namespace foo { typedef int moo; }
typedef int moo;
using namespace foo;
extern moo a;

在 g++ 和 clang++ 中编译(-Weverything 没有警告)。 MSVC 拒绝它,因为它的符号不明确。

这正是 gcc 标头中 size_t 的情况。它在namespace std 的内外都进行了类型定义。这似乎不会导致任何问题 g++。

为什么在 g++ 中编译而不是在 msvc 中编译?我猜这是因为对 7.1.3/3 的不同解释

在给定的非类范围内,typedef 说明符可用于重新定义在该范围内声明的任何类型的名称,以引用它已经引用的类型。

诚然,g++ 的解释相当松散。第一个 moo 未在 namespace :: 中声明,因此该规则似乎不适用。我找不到其他任何东西可以允许这样的事情。

为了解决这个问题,我会修补在全局命名空间中定义size_t 的标头,并将声明带入namespace std(有条件地,如果定义了__cplusplus)。但是我没有测试过(这里没有VC2017),不能保证它会起作用。

我也不知道为什么您的代码会被实际编译器接受而只被 IntelliSense 拒绝。我已经用实际的编译器测试了这个结构。 (更新到最后一句话:我已经用 MSVC 测试过代码,但被 MSVC 拒绝了。在意识到上面的“实际编译器”实际上是 gcc 而不是 MSVC 之前,我已经进行了测试) .

【讨论】:

  • 它实际上被gcc接受(因为来自vc 2017的linux项目是在linux目标系统上远程编译的)
  • 哦,我明白了。这是有道理的。
  • 7.1.3/3 看起来不适用于这里。在您的第二个typedef int moo; 中,foo::moo 不在范围内。
  • @hvd 这基本上也是我要说的。
  • @hvd 如果这不是标准中的未解决问题,它应该是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
相关资源
最近更新 更多