From e315d63d13a4c5fc8bb7d410b6b89edec975cf68 Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sun, 7 Sep 2025 17:40:00 -0400 Subject: [PATCH] Add some tuple algorithms. Mostly car/cdr and reversal. --- Utility/CMakeLists.txt | 1 + Utility/tuple_algorithms.h | 76 ++++++++++++++++++++ Utility/tuple_algorithms.test/0.cc | 61 ++++++++++++++++ Utility/tuple_algorithms.test/CMakeLists.txt | 1 + 4 files changed, 139 insertions(+) create mode 100644 Utility/tuple_algorithms.h create mode 100644 Utility/tuple_algorithms.test/0.cc create mode 100644 Utility/tuple_algorithms.test/CMakeLists.txt diff --git a/Utility/CMakeLists.txt b/Utility/CMakeLists.txt index 6410db3..f8e8e4f 100644 --- a/Utility/CMakeLists.txt +++ b/Utility/CMakeLists.txt @@ -6,3 +6,4 @@ add_subdirectory( derived_pointer_cast.test ) add_subdirectory( print_number.test ) add_subdirectory( NamedOperator.test ) add_subdirectory( NamedComparator.test ) +add_subdirectory( tuple_algorithms.test ) diff --git a/Utility/tuple_algorithms.h b/Utility/tuple_algorithms.h new file mode 100644 index 0000000..f86238f --- /dev/null +++ b/Utility/tuple_algorithms.h @@ -0,0 +1,76 @@ +static_assert( __cplusplus >= 2023'02 ); + +#pragma once + +#include + +#include +#include + +#include + +namespace Alepha::Hydrogen::Utility ::detail:: tuple_algorithms_m +{ + namespace tuple + { + template< typename First, typename ... Args > + auto car( std::tuple< First, Args... > tuple ); + + auto cdr( Concepts::Tuple auto tuple ); + + template< typename ... Args > + auto reverse( std::tuple< Args... > tuple ); + } + + template< typename First, typename ... Args > + auto + tuple::car( std::tuple< First, Args... > tuple ) + { + return std::get< 0 >( tuple ); + } + + template< std::size_t first, std::size_t ... rest > + auto + cdr_index_sequence( std::index_sequence< first, rest... > ) + { + return std::index_sequence< rest... >{}; + } + + template< typename ... Args > + auto + cdr_indices( const std::tuple< Args... > & ) + { + return cdr_index_sequence( std::make_index_sequence< sizeof...( Args ) >{} ); + } + + template< std::size_t ... ints > + auto + get_indices( Concepts::Tuple auto tuple, std::index_sequence< ints... > ) + { + return std::tuple{ std::get< ints >( tuple )... }; + } + + auto + tuple::cdr( Concepts::Tuple auto tuple ) + { + return get_indices( tuple, cdr_indices( tuple ) ); + } + + template< typename ... Args > + auto + tuple::reverse( std::tuple< Args... > tuple ) + { + if constexpr( sizeof...( Args ) == 0 ) return std::tuple{}; + else return std::tuple_cat( tuple::reverse( cdr( tuple ) ), std::tuple{ car( tuple ) } ); + } + + inline namespace exports + { + namespace tuple= tuple_algorithms_m::tuple; + } +} + +namespace Alepha::Hydrogen::Utility::inline exports::inline tuple_algorithms_m +{ + using namespace detail::tuple_algorithms_m::exports; +} diff --git a/Utility/tuple_algorithms.test/0.cc b/Utility/tuple_algorithms.test/0.cc new file mode 100644 index 0000000..2daa233 --- /dev/null +++ b/Utility/tuple_algorithms.test/0.cc @@ -0,0 +1,61 @@ +static_assert( __cplusplus >= 2023'02 ); + +#include + +#include +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + using namespace Alepha::Testing::literals; + + "Does an empty tuple reverse?"_test <=TableTest + < + Alepha::Utility::tuple::reverse<> + > + ::Cases + { + { "No arguments", { {} }, {} }, + }; + + "Does an single entry reverse?"_test <=TableTest + < + Alepha::Utility::tuple::reverse< int > + > + ::Cases + { + { "No arguments (42)", { { 42 } }, { 42 } }, + { "No arguments (2600)", { { 2600 } }, { 2600 } }, + }; + + "Does a pair of entries reverse?"_test <=TableTest + < + Alepha::Utility::tuple::reverse< int, std::string > + > + ::Cases + { + { "No arguments (42, 'Hello')", { { 42, "Hello" } }, { "Hello", 42 } }, + { "No arguments (2600, 'Goodbye')", { { 2600, "Goodbye" } }, { "Goodbye", 2600 } }, + }; + + "Does a trio of entries reverse (first and last same)?"_test <=TableTest + < + Alepha::Utility::tuple::reverse< int, std::string, int > + > + ::Cases + { + { "No arguments (42, 'Hello')", { { 42, "Hello", 127 } }, { 127, "Hello", 42 } }, + { "No arguments (2600, 'Goodbye')", { { 2600, "Goodbye", 77 } }, { 77, "Goodbye", 2600 } }, + }; + + "Does a trio of entries reverse (first and last differ)?"_test <=TableTest + < + Alepha::Utility::tuple::reverse< int, std::string, double > + > + ::Cases + { + { "No arguments (42, 'Hello')", { { 42, "Hello", 2.71828 } }, { 2.71828, "Hello", 42 } }, + { "No arguments (2600, 'Goodbye')", { { 2600, "Goodbye", 3.14159 } }, { 3.14159, "Goodbye", 2600 } }, + }; +}; diff --git a/Utility/tuple_algorithms.test/CMakeLists.txt b/Utility/tuple_algorithms.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Utility/tuple_algorithms.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )