static_assert( __cplusplus > 2020'99 ); #pragma once #include #include #include #include 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; }