'_HAS_CXX17'marco是否可用于自定义项目标题中以启用C ++ 17语言集功能?

时间:2018-09-18 04:59:52

标签: c++ visual-studio-2017 boost-optional stdoptional

我想创建使用标准C ++中的“可选”标题。 但是,将从Visual Studio 2015以及Visual Studio 2017项目中引用我的标头。

我想要一些东西,例如对于Visual Studio 2017(设置了C ++ 17 lang功能),使用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'宏可以吗? 有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

简短的答案是:在Visual C ++ Runtime的实现中依赖内部预处理器定义并不安全,从技术上讲,所有以单个_开头的编译器符号都是保留供实施使用。

例如,_NOEXCEPT已在Visual Studio 2015和2017中内部使用,但是从VS 2017开始(15.8更新),此宏不再存在;请参阅。标头仅直接使用noexcept

推荐使用__has_include是好的,但在VS 2017(15.3更新)之前不受支持。

另一个挑战是__cplusplus并不表示您正在使用/std:c++17,除非您使用的是VS 2017(更新了15.7版),并且新的/Zc:__cplusplus开关默认情况下处于关闭状态。

在多个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
  

请参见Visual C++ Language Conformance