From b5fb8c76f2dcb5d4965b3dd4eeb2c6b3344125e6 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Fri, 5 Jul 2024 11:54:01 -0400 Subject: [PATCH] Create C++26(?) emulation of `template for`. --- CMakeLists.txt | 1 + template_for_each.h | 27 +++++++++++++++++ template_for_each.test/0.cc | 42 +++++++++++++++++++++++++++ template_for_each.test/CMakeLists.txt | 1 + 4 files changed, 71 insertions(+) create mode 100644 template_for_each.test/0.cc create mode 100644 template_for_each.test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b9f4118..2a95f4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ add_subdirectory( comparisons.test ) add_subdirectory( Exception.test ) add_subdirectory( word_wrap.test ) add_subdirectory( string_algorithms.test ) +add_subdirectory( template_for_each.test ) add_subdirectory( tuplize_args.test ) add_subdirectory( Thread.test ) add_subdirectory( assertion.test ) diff --git a/template_for_each.h b/template_for_each.h index 1ec5d61..a3a30a7 100644 --- a/template_for_each.h +++ b/template_for_each.h @@ -8,6 +8,8 @@ static_assert( __cplusplus > 2020'99 ); #include +#include + namespace Alepha::Hydrogen ::detail:: template_for_each_m { inline namespace exports @@ -79,6 +81,31 @@ namespace Alepha::Hydrogen ::detail:: template_for_each_m { 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 ); + } } } diff --git a/template_for_each.test/0.cc b/template_for_each.test/0.cc new file mode 100644 index 0000000..628f23a --- /dev/null +++ b/template_for_each.test/0.cc @@ -0,0 +1,42 @@ +static_assert( __cplusplus > 2023'00 ); + +#include "../template_for_each.h" + +#include +#include + +#include + +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::literals; + using namespace Alepha::Testing::exports; + + struct Example + { + int x; + std::string s; + int y; + }; + + "Can one `template_for` each over a simple struct and get the members into a string?"_test <=TableTest + < + []( Example ex ) + { + using Alepha::template_for; + std::ostringstream oss; + template_for( ex ) <=[&]( const auto &element ) + { + oss << element << std::endl; + }; + + return oss.str(); + } + > + ::Cases + { + { "Simple case", { { 42, "Hello World", 1138 } }, "42\nHello World\n1138\n" }, + }; +}; diff --git a/template_for_each.test/CMakeLists.txt b/template_for_each.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/template_for_each.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )