diff --git a/Utility/CMakeLists.txt b/Utility/CMakeLists.txt index 2c1bf06..6410db3 100644 --- a/Utility/CMakeLists.txt +++ b/Utility/CMakeLists.txt @@ -4,3 +4,5 @@ target_sources( alepha PRIVATE add_subdirectory( derived_pointer_cast.test ) add_subdirectory( print_number.test ) +add_subdirectory( NamedOperator.test ) +add_subdirectory( NamedComparator.test ) diff --git a/Utility/NamedComparator.h b/Utility/NamedComparator.h new file mode 100644 index 0000000..2de3bf3 --- /dev/null +++ b/Utility/NamedComparator.h @@ -0,0 +1,61 @@ +static_assert( __cplusplus > 2023'00 ); + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace Alepha::Hydrogen::Utility ::detail:: NamedComparator_m +{ + inline namespace exports + { + using ComparatorName= Enum + < + "eq"_value, + "ne"_value, + "lt"_value, + "gt"_value, + "le"_value, + "ge"_value + >; + } + + struct comparator + { + constexpr auto + operator () ( const ComparatorName &lhs, const ComparatorName &rhs ) const + { + return lhs.get_index() < rhs.get_index(); + } + }; + + namespace exports + { + template< typename Type > + auto + getComparatorMap() + { + std::map< ComparatorName, std::function< bool ( Type, Type ) >, comparator > rv + { + { "eq"_value, std::equal_to<>{} }, + { "ne"_value, std::not_equal_to<>{} }, + { "lt"_value, std::less<>{} }, + { "gt"_value, std::greater<>{} }, + { "le"_value, std::less_equal<>{} }, + { "ge"_value, std::greater_equal<>{} }, + }; + + return rv; + }; + } +} + +namespace Alepha::Hydrogen::Utility::inline exports::inline NamedComparator_m +{ + using namespace detail::NamedComparator_m::exports; +} diff --git a/Utility/NamedComparator.test/0.cc b/Utility/NamedComparator.test/0.cc new file mode 100644 index 0000000..2773236 --- /dev/null +++ b/Utility/NamedComparator.test/0.cc @@ -0,0 +1,46 @@ +static_assert( __cplusplus > 2023'00 ); + +#include "../NamedComparator.h" + +#include +#include + +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + using namespace Alepha::Utility::NamedComparator_m; + using namespace Alepha::literals::enum_literals; + + "Does the named comparator system have the expected basic functionality?"_test <= TableTest + < + []( const int lhs, const ComparatorName name, const int rhs ) + { + return getComparatorMap< int >().at( name )( lhs, rhs ); + } + > + ::Cases + { + { "equals (true)", { 1, "eq"_value, 1 }, true }, + { "equals (false)", { 1, "eq"_value, 2 }, false }, + + { "not equals (true)", { 1, "ne"_value, 2 }, true }, + { "not equals (false)", { 1, "ne"_value, 1 }, false }, + + { "less (true)", { 1, "lt"_value, 2 }, true }, + { "less (false)", { 1, "lt"_value, 1 }, false }, + + { "greater (true)", { 2, "gt"_value, 1 }, true }, + { "greater (false)", { 1, "gt"_value, 1 }, false }, + + + { "less equal (true)", { 1, "le"_value, 2 }, true }, + { "less equal (true)", { 1, "le"_value, 1 }, true }, + { "less equal (false)", { 1, "le"_value, 0 }, false }, + + { "greater equal (true)", { 2, "ge"_value, 1 }, true }, + { "greater equal (true)", { 1, "ge"_value, 1 }, true }, + { "greater equal (false)", { 0, "ge"_value, 1 }, false }, + }; +}; diff --git a/Utility/NamedComparator.test/CMakeLists.txt b/Utility/NamedComparator.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Utility/NamedComparator.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 ) diff --git a/Utility/NamedOperator.h b/Utility/NamedOperator.h new file mode 100644 index 0000000..090fbbc --- /dev/null +++ b/Utility/NamedOperator.h @@ -0,0 +1,63 @@ +static_assert( __cplusplus > 2023'00 ); + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace Alepha::Hydrogen::Utility ::detail:: NamedOperator_m +{ + inline namespace exports + { + using OperatorName= Enum + < + "add"_value, + "sub"_value, + "mul"_value, + "mod"_value, + "idiv"_value + >; + } + + struct comparator + { + constexpr auto + operator () ( const OperatorName &lhs, const OperatorName &rhs ) const + { + return lhs.get_index() < rhs.get_index(); + } + }; + + namespace exports + { + template< typename Type > + auto + getOperatorMap() + { + std::map< OperatorName, std::function< Type ( Type, Type ) >, comparator > rv + { + { "add"_value, std::plus<>{} }, + { "sub"_value, std::minus<>{} }, + { "mul"_value, std::multiplies<>{} }, + { "mod"_value, std::modulus<>{} }, + }; + + if constexpr( std::is_integral_v< Type > ) + { + rv[ "idiv"_value ]= std::divides<>{}; + } + + return rv; + }; + } +} + +namespace Alepha::Hydrogen::Utility::inline exports::inline NamedOperator_m +{ + using namespace detail::NamedOperator_m::exports; +} diff --git a/Utility/NamedOperator.test/0.cc b/Utility/NamedOperator.test/0.cc new file mode 100644 index 0000000..5fe2c0c --- /dev/null +++ b/Utility/NamedOperator.test/0.cc @@ -0,0 +1,31 @@ +static_assert( __cplusplus > 2023'00 ); + +#include "../NamedOperator.h" + +#include +#include + +#include + +static auto init= Alepha::Utility::enroll <=[] +{ + using namespace Alepha::Testing::exports; + using namespace Alepha::Utility::NamedOperator_m; + using namespace Alepha::literals::enum_literals; + + "Does the named operator system have the expected basic functionality?"_test <= TableTest + < + []( const int lhs, const OperatorName name, const int rhs ) + { + return getOperatorMap< int >().at( name )( lhs, rhs ); + } + > + ::Cases + { + { "addition", { 1, "add"_value, 1 }, 2 }, + { "subtraction", { 1, "sub"_value, 1 }, 0 }, + { "multiplication", { 5, "mul"_value, 5 }, 25 }, + { "modulus", { 9, "mod"_value, 5 }, 4 }, + { "division", { 5, "idiv"_value, 3 }, 1 }, + }; +}; diff --git a/Utility/NamedOperator.test/CMakeLists.txt b/Utility/NamedOperator.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Utility/NamedOperator.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 )