Ish*_*ita 7 c++ boost-optional visual-studio-2017 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
Run Code Online (Sandbox Code Playgroud)
这样使用'_HAS_CXX17'宏可以吗?有没有更好的方法来做到这一点?
简短的回答是:否。在 Visual C++ 运行时的实现中依赖内部预处理器定义是不安全的,从技术上讲,所有以 single 开头的编译器符号都_保留供实现使用。
例如,_NOEXCEPT已经在 Visual Studio 2015 和 2017 内部使用,但从 VS 2017(15.8 更新)开始,这个宏不再存在;标题noexcept直接使用即可。
建议使用__has_include很好,但在 VS 2017(15.3 更新)之前不受支持。
另一个挑战是,除非您使用 VS 2017(15.7 更新)和默认关闭的新开关,__cplusplus否则并不表明您正在使用。/std:c++17/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
Run Code Online (Sandbox Code Playgroud)