1
0
forked from Alepha/Alepha

Split up the evaluation helpers into specific files.

This commit is contained in:
2024-05-07 22:41:57 -04:00
parent f47b942e28
commit a1137d3a56
4 changed files with 216 additions and 152 deletions

63
Utility/evaluate.h Normal file
View File

@ -0,0 +1,63 @@
static_assert( __cplusplus > 2020'99 );
#pragma once
#include <Alepha/Alepha.h>
#include <utility>
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;
}