Я хочу создать заголовки, которые используют «опционально» из стандартного C ++.
Тем не менее, мои заголовки будут ссылаться из Visual Studio 2015, а также проектов Visual Studio 2017.
Я хотел бы иметь что-то, например, для Visual Studio 2017 (с набором функций языка C ++ 17 lang), используется std :: extra, а в Visual Studio 2015 используется boost :: option.
Я думаю о чем-то вроде этого:
#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 ++ и технически все символы компилятора, которые начинаются с одного _
зарезервированы для использования реализацией.
Например, _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 ++
Других решений пока нет …