1
0
forked from Alepha/Alepha

Unify everything to template_for form.

This commit is contained in:
2024-07-05 12:18:18 -04:00
parent 32e6c36570
commit 970cfa3b62
5 changed files with 91 additions and 86 deletions

View File

@ -51,7 +51,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: IStreamable_m
int index= 0; int index= 0;
// TODO: Consider the lens system here... but the basic use case seems to be for // TODO: Consider the lens system here... but the basic use case seems to be for
// aggregates, so we'll go with this simple case for now... // aggregates, so we'll go with this simple case for now...
tuple_for_each( decomposed ) <=[&]( auto &element ) template_for( decomposed ) <=[&]( auto &element )
{ {
std::istringstream iss{ tokens.at( index++ ) }; std::istringstream iss{ tokens.at( index++ ) };
iss >> element; iss >> element;

View File

@ -45,7 +45,7 @@ namespace Alepha::Hydrogen::IOStreams ::detail:: OStreamable_m
// TODO: Consider the lens system here... but the basic use case seems to be for // TODO: Consider the lens system here... but the basic use case seems to be for
// aggregates, so we'll go with this simple case for now... // aggregates, so we'll go with this simple case for now...
tuple_for_each( decomposed ) <=[&]( const auto &element ) template_for( decomposed ) <=[&]( const auto &element )
{ {
os << NextItem << element; os << NextItem << element;
}; };

View File

@ -206,7 +206,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: TableTest_m
oss << std::endl << "Test inputs were: " << std::endl; oss << std::endl << "Test inputs were: " << std::endl;
int index= 0; int index= 0;
tuple_for_each( params ) <=[&]( const auto &param ) template_for( params ) <=[&]( const auto &param )
{ {
// Debugging output for test inputs is relaxed, as it's not required they be streamable? // Debugging output for test inputs is relaxed, as it's not required they be streamable?
oss << "Argument " << index++ << ": " << streamAdaptValue< OutputMode::Relaxed >( param ) << std::endl; oss << "Argument " << index++ << ": " << streamAdaptValue< OutputMode::Relaxed >( param ) << std::endl;

View File

@ -108,7 +108,7 @@ namespace Alepha::Hydrogen::Testing ::detail:: printDebugging_m
else if constexpr( Meta::is_tuple_v< T > ) else if constexpr( Meta::is_tuple_v< T > )
{ {
oss << '['; oss << '[';
tuple_for_each( v ) <=[&oss, first= true]( const auto &elem ) mutable template_for( v ) <=[&oss, first= true]( const auto &elem ) mutable
{ {
if( not first ) oss << ", "; if( not first ) oss << ", ";
first= false; first= false;

View File

@ -14,98 +14,103 @@ namespace Alepha::Hydrogen ::detail:: template_for_each_m
{ {
inline namespace exports inline namespace exports
{ {
constexpr void tuple_for_each( const std::tuple<> &, const Functional auto ) noexcept {} template< Tuple Type >
[[nodiscard]]
constexpr auto
template_for( Type &tuple ) noexcept;
template< typename ... Args, typename Function > 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 constexpr void
tuple_for_each( const std::tuple< Args... > &tuple, Function body ) operator <= ( Function &&func ) noexcept( noexcept( template_for_impl( tuple, std::forward< Function >( func ) ) ) )
noexcept
(
( ... and noexcept( body( std::declval< const Args & >() ) ) )
)
{ {
const auto callWrapper= [&body]( auto &&element ) { body( element ); return nullptr; }; return template_for_impl( tuple, std::forward< Function >( func ) );
auto loop_body_handler= [&]( auto &&... tuple_elements )
{
std::nullptr_t expansion[]= { callWrapper( tuple_elements )... };
std::ignore= expansion;
};
std::apply( loop_body_handler, tuple );
} }
// Apply type_identity to all tuple elements constexpr operator decltype( std::ignore ) () const= delete;
template< typename > struct type_identify_tuple; };
template< typename T > template< typename Tuple >
using type_identify_tuple_t= typename type_identify_tuple< T >::type; [[nodiscard]]
constexpr auto
template_for_impl( Tuple &tuple ) noexcept
{
return syntax_adaptor< Tuple >{ tuple };
}
template<> struct type_identify_tuple< std::tuple<> > { using type= std::tuple<>; }; template< typename Tuple >
[[nodiscard]]
constexpr auto
template_for_impl( const Tuple &tuple ) noexcept
{
return syntax_adaptor< const Tuple >{ tuple };
}
template< typename ... Args >
struct type_identify_tuple< std::tuple< Args... > >
{
using type= std::tuple< std::type_identity< Args >... >;
};
// Nicer for-each syntax helper: template< Tuple Type >
template< typename Tuple > [[nodiscard]]
struct for_each_syntax_adaptor constexpr auto
{ exports::template_for( Type &tuple ) noexcept
Tuple &tuple; {
return template_for_impl( tuple );
}
template< typename Function > template< Tuple Type >
constexpr void [[nodiscard]]
operator <= ( Function &&func ) noexcept( noexcept( tuple_for_each( tuple, std::forward< Function >( func ) ) ) ) constexpr auto
{ exports::template_for( const Type &tuple ) noexcept
return tuple_for_each( tuple, std::forward< Function >( func ) ); {
} return template_for_impl( tuple );
constexpr operator decltype( std::ignore ) () const= delete;
};
template< typename Tuple >
[[nodiscard]]
constexpr auto
tuple_for_each( Tuple &tuple ) noexcept
{
return for_each_syntax_adaptor< Tuple >{ tuple };
}
template< typename Tuple >
[[nodiscard]]
constexpr auto
tuple_for_each( const Tuple &tuple ) noexcept
{
return for_each_syntax_adaptor< const Tuple >{ tuple };
}
template< typename Type >
concept TemplateLoopable= false
or Tuple< Type >
or Aggregate< Type >
// or Array< T > // Do we need array support? Does it matter?
;
template< TemplateLoopable Type >
[[nodiscard]]
constexpr auto
template_for( Type &tuple, std::optional< Reflection::aggregate_tuple_t< Type > > &&tupled= {} ) noexcept
{
tupled= Reflection::tuplizeAggregate( tuple );
return tuple_for_each( *tupled );
}
template< TemplateLoopable Type >
[[nodiscard]]
constexpr auto
template_for( const Type &tuple, std::optional< Reflection::aggregate_tuple_t< Type > > &&tupled= {} ) noexcept
{
tupled= Reflection::tuplizeAggregate( tuple );
return tuple_for_each( *tupled );
}
} }
} }