summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compat/macros.hpp23
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>