I want to create headers which use 'optional' from standard C++. However, My headers will be referred from Visual Studio 2015 as well as Visual Studio 2017 projects.
I would like to have something, such that for Visual Studio 2017 ( with C++ 17 lang feature set) , std::optional is used and with Visual Studio 2015, boost::optional gets used.
I am thinking of something like this:
#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
Is it okay to use '_HAS_CXX17' macro this way? Is there a better way of doing this?
The short answer is: No It's not safe to rely on internal preprocessor defines in the implementation of the Visual C++ Runtime, and technically all compiler symbols that begin with a single
_
are reserved for use by the implementation.For example,
_NOEXCEPT
has been used internally in Visual Studio 2015 and 2017, but as of VS 2017 (15.8 update), this macro no longer exists; the headers just usenoexcept
directly.The recommendation to use
__has_include
is good, but isn't supported prior to VS 2017 (15.3 update).The other challenge is that
__cplusplus
doesn't indicate you are using/std:c++17
unless you are using VS 2017 (15.7 update) with the new/Zc:__cplusplus
switch which is off by default.Probably the safest way to do this across a range of VS versions would be: