Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2017: ambiguous symbol size_t in linux projects

In Visual Studio 2017 when creating Linux project and inserting using namespace std; in source code like this:

#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 underlines size_t and says that it is an ambiguous symbol.VS pic 1

If I press F12 (Go to definition) it offers me two definition places:

From 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;
// ...

And 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;
// ...

It happens only with Linux projects in VS, not with Windows projects.

Is there any known solution (except for "do not use using namespace std; :) )?

Upd: Reported this problem to Microsoft: https://developercommunity.visualstudio.com/content/problem/67405/ambiguous-symbol-size-t-in-linux-projects-when-usi.html

Upd2: Microsoft says that they fixed it, and solution will be in next update: https://developercommunity.visualstudio.com/content/problem/67405/ambiguous-symbol-size-t-in-linux-projects-when-usi.html

like image 745
vladon Avatar asked Jun 11 '17 13:06

vladon


1 Answers

It looks like there is a difference between Microsoft's and other compilers related to typedef in and out of a namespace.

This source file

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

compiles in g++ and clang++ (no warnings with -Weverything). MSVC rejects it because of an ambiguous symbol.

This is exactly the situation with size_t in gcc headers. It is typedefed both in and out of namespace std. This doesn't seem to cause any problems with g++.

Why does this compile in g++ and not in msvc? I guess this is because of different interpretation of 7.1.3/3

In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.

Admittedly the interpretation by g++ is rather loose. The first moo is not declared within namespace :: so the rule seemingly doesn't apply. I cannot find anything else that would permit such a thing.

To solve the problem, I would patch the header where size_t is defined in the global namespace, and bring the declaration inside namespace std (conditionally, if __cplusplus is defined). But I have not tested it (no VC2017 here) and cannot guarantee it will work.

I also have no idea why your code is accepted by the actual compiler and only rejected by IntelliSense. I have tested this construction with actual compilers. (update to the last sentence: I have had the code tested with, and rejected by, MSVC. I have conducted the tests before realising that "the actual compiler" above is in fact gcc and not MSVC).

like image 114
n. 1.8e9-where's-my-share m. Avatar answered Sep 30 '22 19:09

n. 1.8e9-where's-my-share m.