diff --git a/Functional/CMakeLists.txt b/Functional/CMakeLists.txt index 8802363..ddede34 100644 --- a/Functional/CMakeLists.txt +++ b/Functional/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory( composition.test ) +add_subdirectory( reverse_arguments.test ) diff --git a/Functional/reverse_arguments.h b/Functional/reverse_arguments.h new file mode 100644 index 0000000..3650391 --- /dev/null +++ b/Functional/reverse_arguments.h @@ -0,0 +1,55 @@ +static_assert( __cplusplus >= 2023'02 ); + +#pragma once + +#include + +#include + +#include + +namespace Alepha::Hydrogen::Functional ::detail:: reverse_arguments_m +{ + inline namespace exports + { + auto reverse_arguments( Concepts::Functional auto func ); + } + + template< typename Result, typename ... Arguments > + auto + build_reverse_tuple_lambda( std::function< Result ( Arguments... ) > func ) + { + return std::function + { + [func]( decltype( Utility::tuple::reverse( std::declval< std::tuple< Arguments... > >() ) ) params ) + { + return std::apply( func, Utility::tuple::reverse( params ) ); + } + }; + } + + template< typename ReturnType, typename ... Arguments > + auto + bind_args_to_tuple_function( std::function< ReturnType ( std::tuple< Arguments... > ) > func ) + { + return std::function + { + [func]( Arguments... args ) -> ReturnType + { + return func( std::tuple{ args... } ); + } + }; + } + + auto + exports::reverse_arguments( Concepts::Functional auto func ) + { + return bind_args_to_tuple_function( build_reverse_tuple_lambda( std::function{ func } ) ); + } +} + +namespace Alepha::Hydrogen::Functional::inline exports::inline reverse_arguments_m +{ + using namespace detail::reverse_arguments_m::exports; +} + diff --git a/Functional/reverse_arguments.test/0.cc b/Functional/reverse_arguments.test/0.cc new file mode 100644 index 0000000..f8e2b9e --- /dev/null +++ b/Functional/reverse_arguments.test/0.cc @@ -0,0 +1,31 @@ +static_assert( __cplusplus >= 2023'02 ); + +#include + +#include +#include + +static auto +addOneToAllArgs( int a, int b, int c ) +{ + return std::tuple{ a + 1, b + 1, c + 1 }; +} + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + using namespace Alepha::Testing::literals; + + + "Reverse add one"_test <=TableTest + < + []( int c, int b, int a ) + { + return Alepha::Functional::reverse_arguments( addOneToAllArgs )( c, b, a ); + } + > + ::Cases + { + { "Smoke test", { 1, 2, 3 }, { 4, 3, 2 } }, + }; +}; diff --git a/Functional/reverse_arguments.test/CMakeLists.txt b/Functional/reverse_arguments.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Functional/reverse_arguments.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )