diff options
-rw-r--r-- | compat/macros.hpp | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/compat/macros.hpp b/compat/macros.hpp index a6f3d0e9..f7fa8f73 100644 --- a/compat/macros.hpp +++ b/compat/macros.hpp @@ -51,6 +51,21 @@ // from now only C++ #include <utility> +#include <type_traits> + +// before C++20 +namespace cxx20_compat { + template<typename T> + struct remove_cvref { + using type = std::remove_cv_t<std::remove_reference_t<T>>; + }; +} // ns cxx20_compat + +template<typename t> +using remove_cvref_t = typename cxx20_compat::remove_cvref<t>::type; + +template<typename t> +using to_const_lvalue_reference_t = remove_cvref_t<t> const&; // causes ICE in Visual Studio 2017 Preview. the ICE was reported and they handle them seriously in due time. // the ICE is caused by decltype(auto) and const& return value @@ -58,8 +73,12 @@ #define eval_once(expr) eval_once__2(expr, PP_CAT(_EVAL_ONCE__, __COUNTER__)) #define eval_once__2(expr, ident) eval_once__3(expr, ident) -#define eval_once__3(expr, ident) \ - ([&]() -> std::decay_t<decltype(expr)> const& { static const std::decay_t<decltype(expr)> INIT##ident = (expr); return INIT##ident; }()) + +#define eval_once__3(expr, ident) \ + ([&] { \ + static auto INIT##ident = (expr); \ + return static_cast<to_const_lvalue_reference_t<decltype(INIT##ident)>>(INIT##ident); \ + }()) #include <type_traits> |