diff --git a/src/core/include/megbrain/utils/metahelper_basic.h b/src/core/include/megbrain/utils/metahelper_basic.h index c70adacf68d00f8935022ca13b90e6d43677dde3..c00048acdb7f3249f52939699dc38b2df7f1e6be 100644 --- a/src/core/include/megbrain/utils/metahelper_basic.h +++ b/src/core/include/megbrain/utils/metahelper_basic.h @@ -73,6 +73,32 @@ namespace metahelper_detail { static std::false_type test(...); using type = decltype(test(reinterpret_cast(0))); }; + + struct if_constexpr_identity { + template + decltype(auto) operator()(T&& x) { + return std::forward(x); + } + }; + + template + struct if_constexpr_impl; + + template <> + struct if_constexpr_impl { + template + static decltype(auto) run(Then&& then, Else&&) { + return then(if_constexpr_identity{}); + } + }; + + template <> + struct if_constexpr_impl { + template + static decltype(auto) run(Then&&, Else&& else_) { + return else_(if_constexpr_identity{}); + } + }; } // namespace metahelper_detail //! construct index_sequence<0..N-1> @@ -304,6 +330,20 @@ T raw_cast(U&& u) { return x.t; } +//! functionally equivalent to "if constexpr" in C++17. +//! then/else callbacks receives an Identity functor as its sole argument. +//! The functor is useful for masking eager type check on generic lambda, +//! preventing syntax error on not taken branches. +template +decltype(auto) if_constexpr(Then&& then, Else&& else_) { + return metahelper_detail::if_constexpr_impl::run(then, else_); +} + +template +decltype(auto) if_constexpr(Then&& then) { + return if_constexpr(std::forward(then), [](auto) {}); +} + } // namespace mgb // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}