7

我想创建使用标准 C++ 中的“可选”的标头。但是,我的标头将引用自 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”宏可以吗?有没有更好的方法来做到这一点?

4

1 回答 1

3

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

例如,_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

请参阅Visual C++ 语言一致性

于 2018-09-18T05:19:02.650 回答