C2386:'void_t':当前范围

时间:2017-12-04 21:37:11

标签: c++ cmake visual-studio-2017 c++14

我正在开发 Qt 项目,该项目旨在构建在 Windows Linux 上。作为构建系统,我在Ubuntu 16.04上使用GCC 5.4 CMake ,在Windows 10上使用Visual Studio 2017.因为当前使用的标准是但我想使用便捷类型{{ 3}}我将其定义如下:

#if __cplusplus >= 201703L
#include <type_traits>
#else
namespace std {
template<typename... Ts> struct make_void { typedef void type; };
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
}
#endif

如果我使用上面提到的编译器在Linux下构建项目,上面的定义工作正常,但是当我尝试在Windows下构建它时,我收到以下错误消息:

C2386: 'void_t': a symbol with this name already exists in the current scope
U1077: 'C:\PROGRA~2\MICROS~4\2017\ENTERP~1\VC\Tools\MSVC\1411~1.255\bin\HostX64\x64\cl.exe' : return code '0x2'
U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\nmake.exe"' : return code '0x2'
U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\nmake.exe"' : return code '0x2'

顶级CMake文件设置C ++标准如下:

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

我不明白为什么当标准设置为std::void_t时,Visual Studio 2017会抱怨std::void_t。这是一种正常行为,我认为错误地以所示方式污染std命名空间不会导致错误吗?如何克服Visual Studio 2017产生的这些错误?

修改:我刚刚注意到依赖预定义宏__cplusplus的值可能会导致unexpected results问题也针对__cplusplus宏。

2 个答案:

答案 0 :(得分:4)

  

这是一种正常的行为,我认为错误地以显示的方式污染std命名空间不会导致错误吗?

标准库拥有namespace std - 您只能在特定情况下向其添加内容。声明全新的类型不是其中之一,你应该不这样做。污染namespace std在某些时候会遇到麻烦。

在这种特殊情况下,使用您自己的void_t而不是标准库版本真的没有什么可失去的。它会工作的。所以就这样做吧。或者,如果您确实想要使用标准名称,请将其中一个或另一个带入不同的名称空间:

namespace xstd {
#if __cplusplus >= 201703L
    using std::void_t;
#else    
    template<typename... Ts> struct make_void { typedef void type; };
    template<typename... Ts> using void_t = typename make_void<Ts...>::type;
#endif
}

// use xstd::void_t throughout

答案 1 :(得分:2)

CMAKE_CXX_STANDARD选项目前对Visual Studio的影响有限。

与提供-std命令行开关以指定所请求的标准版本的gcc或clang不同,Visual C ++过去常常为您提供所有最新功能。仅在2015版本(更新3)中,他们引入了/std option,旨在为较新的语言功能提供选择加入机制。

不幸的是,这还不像gcc或clang那样成熟,所以你可能仍然会得到你不会想到的功能。