无法使用 Visual Studio 和 CMake 将 __cplusplus 设置为 C++17 标准 [英] Cannot set __cplusplus to C++17 standard with Visual Studio and CMake

查看:81
本文介绍了无法使用 Visual Studio 和 CMake 将 __cplusplus 设置为 C++17 标准的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用 Visual Studio 2019 打开的 CMake 项目.我的代码需要 c++17 特性,所以我在 CMakeLists.txt

I've a CMake project that's opened with Visual Studio 2019. I need c++17 features for my code, so I've set the corresponding flag in the CMakeLists.txt

cmake_minimum_required (VERSION 3.10.0)

project (datalog)

message (STATUS "Building project ${PROJECT_NAME}")

find_package(stxxl CONFIG REQUIRED)

include_directories (${CMAKE_SOURCE_DIR}/src)

set (PROJECT_SRC
  main.cpp
  )

add_executable (${PROJECT_NAME} ${PROJECT_SRC})
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)

target_link_libraries(${PROJECT_NAME} stxxl)

当我构建时,我遇到了很多错误,因为我正在链接的库 stxxlvcpkg 一起安装,具有以下代码:

When I build I obtain a lot of errors, because the library that I'm linking, stxxl, installed with vcpkg, has the following piece of code:

STXXL_BEGIN_NAMESPACE

template <class Type>
struct compat_unique_ptr {
#if __cplusplus >= 201103L && ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40400)
    typedef std::unique_ptr<Type> result;
#else
    // auto_ptr is inherently broken and is deprecated by unique_ptr in c++0x
    typedef std::auto_ptr<Type> result;
#endif
};

STXXL_END_NAMESPACE

问题是 __cplusplus 的值是 199711L 而不是正确的值 201703L,因此代码尝试使用在C++17 标准.

The problem is that __cplusplus has value 199711L instead of the correct value 201703L, so code tries to use auto_ptr that's removed in C++17 standard.

我也尝试在 Visual Studio 中手动设置标志,在 CmakeLists.txt

I've also tried to set the flag manually in Visual Studio, adding this section in the CmakeLists.txt

if(MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 /Zc:__cplusplus")
endif()

但没有任何改变.我也在使用一些 C++17 特性,所以现在不能返回.

But nothing changes. I'm also using some C++17 features, so going back at the moment is not an option.

我可以手动更新 stxxl 头文件以摆脱宏,但这是一种解决方法,每个开发人员都应该创建相同的修复程序.相反,我想知道为什么会出现错误以及如何使用 Visual Studio 和 CMake 将宏设置为正确的值.你有什么建议吗?

I can manually update the stxxl header file to get rid of the macro, but it's a workaround, and every developer should create the same fix. Instead, I'd like to know why I'm getting the error and how to set the macro to the correct value with Visual Studio and CMake. Do you have any suggestion?

推荐答案

据我所知 这个,你需要手动添加/Zc:__cplusplus(至少现在是这样).

As far as i can tell from this, you need to add /Zc:__cplusplus manually (at least for now).

您的 CMakeList 片段对我有用,您确定 __cplusplus 实际上设置不正确,而不仅仅是 __GNUC__ 宏,它丢失了吗?

Your CMakeList snippet worked for me, are you sure, that __cplusplus is actually set incorrectly and it's not just the __GNUC__ Macro, that's missing?

也就是说,我建议测试一下 VisualStudio 的版本是否真的足够新:

That said, I'd recommend to test if the version of VisualStudio is actually new enough:

# /Zc:__cplusplus is required to make __cplusplus accurate
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
# (according to https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
# That version is equivalent to _MSC_VER==1914
# (according to https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
if ((MSVC) AND (MSVC_VERSION GREATER_EQUAL 1914))
    target_compile_options(stxxl INTERFACE "/Zc:__cplusplus")
endif()

注意:我使用 target_compile_options 将必要的选项添加到库目标的界面.这样,所有依赖于该库(通过 target_link_libraries)的目标都将使用该标志进行编译,但不需要它(并且可能与其不兼容)的目标将无法获得它.

Note: I used target_compile_options to add the necessary option to the interface of your library target. This way all targets, that depend on that library (via target_link_libraries) will be compiled with that flag, but targets, that don't need it (and might be incompatible with it) won't get it.

如果您想将标志添加到您自己的目标之一,您可以使用 target_compile_options(stxxl PUBLIC "/Zc:__cplusplus") (PUBLIC 而不是 <代码>接口).INTERFACE 表示当其他目标依赖于该目标时使用该选项,PRIVATE 表示该选项用于目标本身,PUBLIC 表示两者.(恕我直言 这篇文章 解释得很好.)

If you want to add the flag to one of your own targets, you can use target_compile_options(stxxl PUBLIC "/Zc:__cplusplus") (PUBLIC instead of INTERFACE). INTERFACE means the option is used when other targets depend on that target, PRIVATE means the option is used for the target itself and PUBLIC means both. (IMHO this artical explains it well.)

除此之外,您不应该通过编译标志设置 c++ 标准版本,而是使用 target_compile_features 如果需要更新版本并使用
set_target_properties(your_target_name PROPERTIES CXX_STANDARD 17)如果您只想使用可用的较新版本.

Apart from that, you shouldn't set the c++ standard version via compile flags, but instead using target_compile_features if the newer version is required and using
set_target_properties(your_target_name PROPERTIES CXX_STANDARD 17) if you just wish to use the newer version if it is available.

在您的情况下,后者可能就足够了,因为如果 c++ 版本较旧,您的代码片段有回退.

In your case the latter is probably sufficient as your codesnippet has a fallback if the c++ version is older.

如果可以选择更改 stxxl 的代码(通过拉取请求等),则代码可以测试 _MSVC_LANG_MSC_VER.这样它就可以在不需要 /Zc:__cplusplus 的情况下工作.

If changing the code of stxxl (via pull request, etc.) is an option, the code could test _MSVC_LANG and _MSC_VER. This way it would work without requiring /Zc:__cplusplus.

这篇关于无法使用 Visual Studio 和 CMake 将 __cplusplus 设置为 C++17 标准的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆