1
0
forked from Alepha/Alepha

Add NamedOperator and NamedComparator.

This permits naming operators via an enhanced enum and then
looking them up.  This is a useful component for quick
development of scripting language functionalities.
This commit is contained in:
2024-07-17 11:45:50 -04:00
7 changed files with 205 additions and 0 deletions

View File

@ -4,3 +4,5 @@ target_sources( alepha PRIVATE
add_subdirectory( derived_pointer_cast.test ) add_subdirectory( derived_pointer_cast.test )
add_subdirectory( print_number.test ) add_subdirectory( print_number.test )
add_subdirectory( NamedOperator.test )
add_subdirectory( NamedComparator.test )

61
Utility/NamedComparator.h Normal file
View File

@ -0,0 +1,61 @@
static_assert( __cplusplus > 2023'00 );
#pragma once
#include <Alepha/Alepha.h>
#include <map>
#include <functional>
#include <type_traits>
#include <Alepha/Enum.h>
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;
}

View File

@ -0,0 +1,46 @@
static_assert( __cplusplus > 2023'00 );
#include "../NamedComparator.h"
#include <Alepha/Testing/test.h>
#include <Alepha/Testing/TableTest.h>
#include <Alepha/Utility/enroll.h>
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 },
};
};

View File

@ -0,0 +1 @@
unit_test( 0 )

63
Utility/NamedOperator.h Normal file
View File

@ -0,0 +1,63 @@
static_assert( __cplusplus > 2023'00 );
#pragma once
#include <Alepha/Alepha.h>
#include <map>
#include <functional>
#include <type_traits>
#include <Alepha/Enum.h>
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;
}

View File

@ -0,0 +1,31 @@
static_assert( __cplusplus > 2023'00 );
#include "../NamedOperator.h"
#include <Alepha/Testing/test.h>
#include <Alepha/Testing/TableTest.h>
#include <Alepha/Utility/enroll.h>
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 },
};
};

View File

@ -0,0 +1 @@
unit_test( 0 )