Added new C++17 function wrappers

etl::function_as_functor
etl::function_ptr_as_functor
etl::functor_as_static
etl::member_function_as_static
etl::member_function_as_functor
This commit is contained in:
John Wellbelove 2024-11-10 11:55:53 +00:00
parent c954c696bb
commit ad69fb256d
2 changed files with 170 additions and 19 deletions

View File

@ -496,7 +496,7 @@ namespace etl
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "Integral types only");
typedef T value_type;
using value_type = T;
static ETL_CONSTEXPR size_t size() ETL_NOEXCEPT
{
@ -504,7 +504,7 @@ namespace etl
}
};
namespace private_integer_sequence
namespace private_index_sequence
{
template <size_t N, typename IndexSeq>
struct make_index_sequence;
@ -512,19 +512,19 @@ namespace etl
template <size_t N, size_t... Indices>
struct make_index_sequence<N, etl::integer_sequence<size_t, Indices...>>
{
typedef typename make_index_sequence<N - 1, etl::integer_sequence<size_t, N - 1, Indices...>>::type type;
using type = typename make_index_sequence<N - 1, etl::integer_sequence<size_t, N - 1, Indices...>>::type;
};
template <size_t... Indices>
struct make_index_sequence<0, etl::integer_sequence<size_t, Indices...>>
{
typedef etl::integer_sequence<size_t, Indices...> type;
using type = etl::integer_sequence<size_t, Indices...>;
};
}
//***********************************
template <size_t N>
using make_index_sequence = typename private_integer_sequence::make_index_sequence<N, etl::integer_sequence<size_t>>::type;
using make_index_sequence = typename private_index_sequence::make_index_sequence<N, etl::integer_sequence<size_t>>::type;
//***********************************
template <size_t... Indices>
@ -601,10 +601,13 @@ namespace etl
#if ETL_USING_CPP11
//*************************************************************************
/// A function wrapper for free/global functions.
// A function wrapper for free/global functions.
// Deprecated.
// See etl::function_ptr_as_functor for a runtime time wrapper option.
// See etl::function_as_functor for a compile time wrapper option.
//*************************************************************************
template <typename TReturn, typename... TParams>
class functor
class ETL_DEPRECATED functor
{
public:
@ -618,7 +621,7 @@ namespace etl
//*********************************
/// Const function operator.
//*********************************
//*********************************
constexpr TReturn operator()(TParams... args) const
{
return ptr(etl::forward<TParams>(args)...);
@ -629,18 +632,18 @@ namespace etl
/// The pointer to the function.
TReturn(*ptr)(TParams...);
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// A wrapper for a member function
// Wrap a member function with a static free function.
// Creates a static member function that calls the specified member function.
// Deprecated
// See etl::member_function_as_static
//*****************************************************************************
template <typename T>
class member_function_wrapper;
class ETL_DEPRECATED member_function_wrapper;
template <typename TReturn, typename... TParams>
class member_function_wrapper<TReturn(TParams...)>
class ETL_DEPRECATED member_function_wrapper<TReturn(TParams...)>
{
public:
@ -650,12 +653,12 @@ namespace etl
return (Instance.*Method)(etl::forward<TParams>(params)...);
}
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// A wrapper for a functor
// Wrap a functor with a static free function.
// Creates a static member function that calls the specified functor.
// Deprecated
// See etl::functor_as_static
//*****************************************************************************
template <typename T>
class functor_wrapper;
@ -672,6 +675,104 @@ namespace etl
}
};
#endif
#if ETL_USING_CPP17
//*****************************************************************************
// Wraps a functor with a static free function at compile time.
// Creates a static member 'function' that calls the specified functor.
//*****************************************************************************
template <auto& Instance>
struct functor_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
{
return (Instance.operator())(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a member function with a static free function at compile time.
// Creates a static member function that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
struct member_function_as_static
{
template <typename... TArgs>
static constexpr auto call(TArgs&&... args)
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a member function with a functor at compile time.
// Creates a functor that calls the specified member function.
//*****************************************************************************
template <auto Method, auto& Instance>
class member_function_as_functor
{
public:
template <typename... TArgs>
constexpr auto operator()(TArgs&&... args) const -> decltype((Instance.*Method)(etl::forward<TArgs>(args)...))
{
return (Instance.*Method)(etl::forward<TArgs>(args)...);
}
};
//*****************************************************************************
// Wraps a function with a functor at compile time.
// Creates a functor that calls the specified free function.
//*****************************************************************************
template <auto Function>
class function_as_functor
{
public:
template<typename... TArgs>
constexpr auto operator()(TArgs&&... args) const -> decltype(Function(etl::forward<TArgs>(args)...))
{
return Function(etl::forward<TArgs>(args)...);
}
};
#endif
#if ETL_USING_CPP11
//*****************************************************************************
// Wraps a function pointer with a functor at run time.
// Creates a functor that calls the specified free function.
//*****************************************************************************
template <typename T>
class function_ptr_as_functor;
template <typename TReturn, typename... TArgs>
class function_ptr_as_functor<TReturn(TArgs...)>
{
public:
//*********************************
/// Constructor.
//*********************************
constexpr function_ptr_as_functor(TReturn(*ptr_)(TArgs...))
: ptr(ptr_)
{
}
//*********************************
/// Const function operator.
//*********************************
constexpr TReturn operator()(TArgs... args) const
{
return ptr(etl::forward<TArgs>(args)...);
}
private:
/// The pointer to the function.
TReturn(*ptr)(TArgs...);
};
#endif
}
#endif

View File

@ -412,14 +412,14 @@ namespace
}
//*************************************************************************
TEST(test_functor)
TEST(test_functor_deprecated)
{
constexpr etl::functor<int, int> fw1(TestGlobal);
CHECK_EQUAL(2, fw1(1));
}
//*************************************************************************
TEST(test_member_function_wrapper)
TEST(test_member_function_wrapper_deprecated)
{
constexpr int(*pf)(int) = &etl::member_function_wrapper<int(int)>::function<TestClass, test, &TestClass::MemberFunction>;
@ -427,13 +427,63 @@ namespace
}
//*************************************************************************
TEST(test_functor_wrapper)
TEST(test_functor_wrapper_deprecated)
{
constexpr int(*pf)(int) = &etl::functor_wrapper<int(int)>::function<TestClass, test>;
CHECK_EQUAL(2, pf(1));
}
//*************************************************************************
#if ETL_USING_CPP17
TEST(test_function_as_functor)
{
constexpr etl::function_as_functor<TestGlobal> faf;
CHECK_EQUAL(2, faf(1));
}
#endif
//*************************************************************************
TEST(test_function_ptr_as_functor)
{
constexpr decltype(TestGlobal)* fptr = TestGlobal;
constexpr etl::function_ptr_as_functor<decltype(TestGlobal)> fpaf(fptr);
CHECK_EQUAL(2, fpaf(1));
}
//*************************************************************************
#if ETL_USING_CPP17
TEST(test_functor_as_static)
{
using fas_t = etl::functor_as_static<test>;
CHECK_EQUAL(2, fas_t::call(1));
}
#endif
//*************************************************************************
#if ETL_USING_CPP17
TEST(test_member_function_as_static)
{
using mfas_t = etl::member_function_as_static<&TestClass::MemberFunction, test>;
CHECK_EQUAL(2, mfas_t::call(1));
}
#endif
#if ETL_USING_CPP17
//*************************************************************************
TEST(test_member_function_as_functor)
{
constexpr etl::member_function_as_functor<&TestClass::MemberFunction, test> mfaf;
CHECK_EQUAL(2, mfaf(1));
}
#endif
//*************************************************************************
struct SF
{