7

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?

Yirkha
  • 12,737
  • 5
  • 38
  • 53
Ishita
  • 489
  • 5
  • 15
  • 3
    Possible duplicate of [How to determine the version of the C++ standard used by the compiler?](https://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler) – Justin Sep 18 '18 at 05:01
  • 1
    Consider using `__has_include()` and `__has_include()` (https://en.cppreference.com/w/cpp/preprocessor/include). Some compilers / standard libraries offer the library features before the actual standard is used. – Justin Sep 18 '18 at 05:03
  • 1
    @Justin given that `__has_include` was added in C++17, using it to detect specific C++17 features sounds problematic. – Sneftel Sep 18 '18 at 05:22
  • @Sneftel Not exactly. You do an `#ifdef __has_include`, then use `__has_include` normally – Justin Sep 18 '18 at 05:27
  • See also the [feature test macros](https://en.cppreference.com/w/cpp/experimental/feature_test) – Justin Sep 18 '18 at 05:29
  • @Justin.. I do not only want the header inclusion, but also the feature inclusion.... just using __has_include will not suffice. – Ishita Sep 18 '18 at 06:08

1 Answers1

3

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 use noexcept 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:

#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

See Visual C++ Language Conformance

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • Does MSVC define the [feature test macros](https://en.cppreference.com/w/cpp/experimental/feature_test)? – Justin Sep 18 '18 at 05:30
  • To be fair, the committee didn't define the feature test macros until C++20 :( See [P0096r5](http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0096r5.html) – Chuck Walbourn Sep 18 '18 at 05:47
  • Thank you @ChuckWalbourn. One thing that concerns me is if we have checked for _MSVC_LANG >= 201703L, then why do we need to check for _MSC_VER? – Ishita Sep 18 '18 at 06:07
  • The ``_MSVC_LANG >= 201703L`` test tells out it's Microsoft Visual C++ with ``/std:c++17`` or ``/std:c++latest`` without ``/Zc:__cplusplus``. You still need to make sure it's VS 2017 (15.3 update) or later before you try to use ``__has_include``. In the case where ``__cplusplus >= 201703L``, then it's VS 2017 (15.7 update) or later already with ``/Zc:__cplusplus`` or some other C++17 Standard compiler. – Chuck Walbourn Sep 18 '18 at 07:44