“_HAS_CXX17”宏是否可用于自定义项目 headers 以启用 C++17 语言集功能?

Is '_HAS_CXX17' macro usable in custom project headers to enable C++17 language set features?

我想创建 headers,它使用来自标准 C++ 的 'optional'。 但是,我的 headers 将从 Visual Studio 2015 年以及 Visual Studio 2017 年的项目中引用。

我想要一些东西,例如 Visual Studio 2017(使用 C++ 17 语言功能集),使用 std::optional 和 Visual Studio 2015,boost::optional 被使用。

我在想这样的事情:

#include <yvals.h>
#if _HAS_CXX17
 #include <optional>
 template <typename T> using Optional = std::optional<T>;
#else
 #include "boost/optional/optional.hpp"
 template <typename T> using Optional = boost::optional<T>;
#endif

可以这样使用“_HAS_CXX17”宏吗? 有更好的方法吗?

简短的回答是:在 Visual C++ 运行时的实现中依赖内部预处理器定义是不安全的,从技术上讲,所有以单个 [ 开头的编译器符号=11=] 保留供实现使用。

比如_NOEXCEPT在Visual Studio2015和2017年内部使用过,但是截至VS 2017(15.8更新),这个宏已经不存在了; headers直接使用noexcept即可。

使用 __has_include 的建议很好,但在 VS 2017(15.3 更新)之前不受支持。

另一个挑战是 __cplusplus 并不表示您正在使用 /std:c++17 除非您使用的是带有新 /Zc:__cplusplus 开关的 VS 2017(15.7 更新)默认。

在一系列 VS 版本中执行此操作的最安全方法可能是:

#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L) && (_MSC_VER >= 1913))
#if __has_include(<optional>)
 #include <optional>
 template <typename T> using Optional = std::optional<T>;
#else
 #include "boost/optional/optional.hpp"
 template <typename T> using Optional = boost::optional<T>;
#endif
#else
 #include "boost/optional/optional.hpp"
 template <typename T> using Optional = boost::optional<T>;
#endif

See Visual C++ Language Conformance