我想创建使用标准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'宏可以吗? 有更好的方法吗?
答案 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