forked from Alepha/Alepha
121 lines
2.6 KiB
C++
121 lines
2.6 KiB
C++
static_assert( __cplusplus > 2020'99 );
|
|
|
|
#pragma once
|
|
|
|
#include <Alepha/Alepha.h>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <Alepha/Concepts.h>
|
|
|
|
#include <Alepha/Reflection/tuplizeAggregate.h>
|
|
|
|
namespace Alepha::Hydrogen ::detail:: template_for_m
|
|
{
|
|
inline namespace exports
|
|
{
|
|
template< Tuple Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for( Type &tuple ) noexcept;
|
|
|
|
template< Tuple Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for( const Type &tuple ) noexcept;
|
|
|
|
template< Aggregate Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for( Type &agg, std::optional< Reflection::aggregate_tuple_t< Type > > &&tupled= {} ) noexcept
|
|
{
|
|
tupled= Reflection::tuplizeAggregate( agg );
|
|
return template_for( *tupled );
|
|
}
|
|
|
|
template< Aggregate Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for( const Type &agg, std::optional< Reflection::aggregate_tuple_t< Type > > &&tupled= {} ) noexcept
|
|
{
|
|
tupled= Reflection::tuplizeAggregate( agg );
|
|
return template_for( *tupled );
|
|
}
|
|
}
|
|
|
|
template< typename ... Args, typename Function >
|
|
constexpr void
|
|
template_for_impl( const std::tuple< Args... > &tuple, Function body )
|
|
noexcept
|
|
(
|
|
( ... and noexcept( body( std::declval< const Args & >() ) ) )
|
|
)
|
|
{
|
|
const auto callWrapper= [&body]( auto &&element ) { body( element ); return nullptr; };
|
|
|
|
auto loop_body_handler= [&]( auto &&... tuple_elements )
|
|
{
|
|
std::nullptr_t expansion[]= { callWrapper( tuple_elements )... };
|
|
|
|
std::ignore= expansion;
|
|
};
|
|
|
|
std::apply( loop_body_handler, tuple );
|
|
}
|
|
|
|
|
|
// Nicer for-each syntax helper:
|
|
template< typename Tuple >
|
|
struct [[nodiscard]] syntax_adaptor
|
|
{
|
|
Tuple &tuple;
|
|
|
|
template< typename Function >
|
|
constexpr void
|
|
operator <= ( Function &&func ) noexcept( noexcept( template_for_impl( tuple, std::forward< Function >( func ) ) ) )
|
|
{
|
|
return template_for_impl( tuple, std::forward< Function >( func ) );
|
|
}
|
|
|
|
constexpr operator decltype( std::ignore ) () const= delete;
|
|
};
|
|
|
|
template< typename Tuple >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for_impl( Tuple &tuple ) noexcept
|
|
{
|
|
return syntax_adaptor< Tuple >{ tuple };
|
|
}
|
|
|
|
template< typename Tuple >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
template_for_impl( const Tuple &tuple ) noexcept
|
|
{
|
|
return syntax_adaptor< const Tuple >{ tuple };
|
|
}
|
|
|
|
|
|
template< Tuple Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
exports::template_for( Type &tuple ) noexcept
|
|
{
|
|
return template_for_impl( tuple );
|
|
}
|
|
|
|
template< Tuple Type >
|
|
[[nodiscard]]
|
|
constexpr auto
|
|
exports::template_for( const Type &tuple ) noexcept
|
|
{
|
|
return template_for_impl( tuple );
|
|
}
|
|
}
|
|
|
|
namespace Alepha::Hydrogen::inline exports::inline template_for_m
|
|
{
|
|
using namespace detail::template_for_m::exports;
|
|
}
|