c++winapic++17std-byte

Including Windows.h is producing errors of: 'byte': ambiguous symbol


I'm getting many errors of the following type. Clearly, Microsoft has a definition of byte that clashes with Standard C++'s definition of std::byte (after a using namespace std, that I use in hundreds of thousands of lines of code, over decades, without any issues whatsoever).

I'm not keen to start adding std:: on practically every line of my software. What are all the various fixes possible, so I can choose the best one?

1>cl /c /I..\..\.. /I"C:\Program Files\MariaDB\MariaDB Connector C 64-bit\include" /I"T:\downloads\MySQL\mysql-9.5.0-winx64\includeXXXXXXXX" /Zi /W3 /WX- /diagnostics:column /sdl /O2 /Oi /GL /D XXXXXXXXXXXXXNDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /std:c++latest /permissive- /Fo"x64\Release\\" /Fd"x64\Release\vc143.pdb" /external:W3 /Gd /TP /FC /errorReport:prompt CompilerHangTest.cpp
1>CompilerHangTest.cpp
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(203,9): error C2872: 'byte': ambiguous symbol
1>(compiling source file 'CompilerHangTest.cpp')
1>    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(202,23):
1>    could be 'unsigned char byte'
1>    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\cstddef(34,24):
1>    or       'std::byte'
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(975,6): error C2872: 'byte': ambiguous symbol
1>(compiling source file 'CompilerHangTest.cpp')
1>    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(202,23):
1>    could be 'unsigned char byte'
1>    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\cstddef(34,24):
1>    or       'std::byte'
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(983,6): error C2872: 'byte': ambiguous symbol
1>(compiling source file 'CompilerHangTest.cpp')
1>    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared\rpcndr.h(202,23):
1>    could be 'unsigned char byte'
1>    C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include\cstddef(34,24):
1>    or       'std::byte'

Solution

  • Many of the default "starter" projects Microsoft provides--and that I usually use--have WIN32_LEAN_AND_MEAN defined before including Windows.h . In contrast, if you write a project by hand--as I did this time--and don't know to define it, you can end up with this symbol conflict.

    WIN32_LEAN_AND_MEAN tells Windows.h not to include a large number of headers that the vast majority of projects don't need, and that includes the headers defining byte in a way that conflicts with Standard C. This will leave you with std::byte (should you include <cstddef> or anything that does) which is what you typically need. It's critical to make this define before Windows.h might possibly be included, but it's not critical to further include Windows.h early. Since almost any header you include might theoretically eventually include Windows.h, the obvious thing to do would be to define WIN32_LEAN_AND_MEAN before including any header.

    #ifdef _WIN32
    // Windows has a symbol byte that conflicts with Standard C++17 or newer
    // std::byte if you've used "using namespace std".  If you're not willing
    // to entirely change your software to eliminate the using, one solution
    // is to define this flag before Windows.h might be included.
    #define WIN32_LEAN_AND_MEAN 0
    #endif
    

    I only mention the following for sake of completeness, and for the very few programmers that actually need the Windows version of byte. I would never do this myself, as harming standards compliance to compensate for a Microsoft error doesn't make sense. Googling around, you'll see some suggestions to put the following at the beginning of your code instead. This also solves the conflict, but only by preventing <cstddef> from defining std::byte. Generally I would never do this unless I had code that actually needed rpcndr.h (and I've never seen such code) and did not need std::byte. That said, you don't need to do the #include especially early, merely get _HAS_STD_BYTE defined before <stddef.h> or <cstddef> is included. And again, since nearly any header could theoretically eventually include <cstddef>, the obvious thing to do, if you have a strong reason to go down this path, would be to define _HAS_STD_BYTE before including any header.

    #define _HAS_STD_BYTE
    #include <stddef.h>
    

    A third solution is to stop using using namespace std and instead pollute your code with spurious references to std:: on every single freaking reference to the standard library. Some people apparently prefer to sit around reading and writing that and have bosses (or are bosses) that are happy to pay them to.