static_assert( __cplusplus > 2020'99 ); #pragma once #include #include namespace Alepha::Hydrogen::Utility ::detail:: evaluate_m { inline namespace exports { /*! * Mechanism to clarify immediately-invoked lambdas. * * Immediately invoked lambdas are a very useful tool. * * ``` * const auto mySortedArray= [&] * { * std::vector< std::string > rv; * // Populate it... * std::sort( begin( rv ), end( rv ) ); * return rv; * }(); * ``` * * The above code defines a sorted vector as const by immediately invoking a lambda to do it. The problem, * however, is that it is entirely unclear whether a lambda is being invoked or defined until the very end * of the lambda's definition is reached. This can become very confusing when there are several nested * levels of lambdas and they get a bit large. * * `evaluate` creates a hook that makes it more clear that it is an immediately-invoked lambda: * * ``` * const auto mySortedArray= evaluate <=[&] * { * std::vector< std::string > rv; * // Populate it... * std::sort( begin( rv ), end( rv ) ); * return rv; * }; * ``` * * Because `evaluate <=` precedes the lambda definition, it is quite clear that something else is going on * here. The `<=` in this case should be thought of as a `fat left arrow` -- the lambda is being put * through an evaluation operation. */ inline struct evaluate_t {} evaluate; } template< typename Function > constexpr decltype( auto ) operator <=( evaluate_t, Function &&func ) noexcept( noexcept( std::forward< Function >( func )() ) ) { return std::forward< Function >( func )(); } } namespace Alepha::Hydrogen::Utility::inline exports::inline evaluate_m { using namespace detail::evaluate_m::exports; }