From this Stack Overflow answer, I learned that C++17 will have __has_include, which can
[make] migrating from experimental to std almost seamless
This still leaves the question of how to do it. Doing something like namespace std { using namespace std::experimental; } is undefined behaviour, so I came up with this method:
optional.h demonstration on coliru
#pragma once #if __has_include(<optional>) # include <optional> # define HAS_STD_OPTIONAL #elif __has_include(<experimental/optional>) # include <experimental/optional> # define HAS_STD_EXPERIMENTAL_OPTIONAL #else # error Must have an optional type, either from <optional> or if not supported from <experimental/optional>. #endif #if defined HAS_STD_OPTIONAL namespace opt { template<class T> using optional = std::optional<T>; using bad_optional_access = std::bad_optional_access; using nullopt_t = std::nullopt_t; using in_place_t = std::in_place_t; constexpr auto nullopt = std::nullopt; constexpr auto in_place = std::in_place; template<class T> constexpr auto make_optional(T && value) { return std::make_optional(std::forward<T>(value)); } } #elif defined HAS_STD_EXPERIMENTAL_OPTIONAL namespace opt { template<class T> using optional = std::experimental::optional<T>; using bad_optional_access = std::experimental::bad_optional_access; using nullopt_t = std::experimental::nullopt_t; using in_place_t = std::experimental::in_place_t; constexpr auto nullopt = std::experimental::nullopt; constexpr auto in_place = std::experimental::in_place; template<class T> constexpr auto make_optional(T && value) { return std::experimental::make_optional(std::forward<T>(value)); } } #endif