mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Add etl::apply (#1509)
Fixes: #1272 Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
parent
ea8eda0147
commit
38f7318a85
@ -249,3 +249,21 @@ template <typename T, typename... Types>
|
||||
ETL_CONSTEXPR14
|
||||
const T&& get(const tuple<Types...>&&);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
template <typename TFunction, typename TTuple>
|
||||
ETL_CONSTEXPR14
|
||||
auto apply(TFunction&& f, TTuple&& t);
|
||||
```
|
||||
|
||||
Invokes the callable object `f` (via `etl::invoke`) with the elements of the tuple `t` expanded as its arguments. Equivalent to `std::apply`.
|
||||
|
||||
```cpp
|
||||
int add(int a, int b, int c) { return a + b + c; }
|
||||
|
||||
auto t = etl::make_tuple(1, 2, 3);
|
||||
int sum = etl::apply(add, t); // sum == 6
|
||||
```
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
#include "functional.h"
|
||||
#include "invoke.h"
|
||||
#include "nth_type.h"
|
||||
#include "type_list.h"
|
||||
#include "type_traits.h"
|
||||
@ -934,6 +935,35 @@ namespace etl
|
||||
return tuple<TTypes&&...>(etl::forward<TTypes>(args)...);
|
||||
}
|
||||
|
||||
namespace private_tuple
|
||||
{
|
||||
//**********************************
|
||||
// Helper for apply.
|
||||
// Invokes the callable with the tuple elements expanded via the index sequence.
|
||||
// Uses an unqualified 'get' so that argument-dependent lookup finds the
|
||||
// appropriate overload for etl::tuple, etl::array, std::tuple, std::pair, etc.
|
||||
//**********************************
|
||||
template <typename TFunction, typename TTuple, size_t... Indices>
|
||||
ETL_CONSTEXPR14 auto apply_impl(TFunction&& f, TTuple&& t, etl::index_sequence<Indices...>)
|
||||
-> decltype(etl::invoke(etl::forward<TFunction>(f), get<Indices>(etl::forward<TTuple>(t))...))
|
||||
{
|
||||
return etl::invoke(etl::forward<TFunction>(f), get<Indices>(etl::forward<TTuple>(t))...);
|
||||
}
|
||||
} // namespace private_tuple
|
||||
|
||||
//***************************************************************************
|
||||
/// Invokes the callable object 'f' with the elements of the tuple 't' as
|
||||
/// arguments. Equivalent to std::apply.
|
||||
//***************************************************************************
|
||||
template <typename TFunction, typename TTuple>
|
||||
ETL_CONSTEXPR14 auto apply(TFunction&& f, TTuple&& t)
|
||||
-> decltype(private_tuple::apply_impl(etl::forward<TFunction>(f), etl::forward<TTuple>(t),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::remove_reference_t<TTuple>>::value>{}))
|
||||
{
|
||||
return private_tuple::apply_impl(etl::forward<TFunction>(f), etl::forward<TTuple>(t),
|
||||
etl::make_index_sequence<etl::tuple_size<etl::remove_reference_t<TTuple>>::value>{});
|
||||
}
|
||||
|
||||
namespace private_tuple
|
||||
{
|
||||
//**********************************
|
||||
|
||||
@ -76,6 +76,32 @@ namespace
|
||||
int i;
|
||||
};
|
||||
|
||||
//*********************************
|
||||
int apply_sum(int a, int b, int c)
|
||||
{
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
//*********************************
|
||||
struct Summer
|
||||
{
|
||||
int operator()(int a, int b) const
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
//*********************************
|
||||
struct Accumulator
|
||||
{
|
||||
int total;
|
||||
|
||||
void add(int a, int b)
|
||||
{
|
||||
total = a + b;
|
||||
}
|
||||
};
|
||||
|
||||
SUITE(test_tuple)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -930,5 +956,61 @@ namespace
|
||||
CHECK_EQUAL(1, i);
|
||||
CHECK_EQUAL(std::string("2"), d.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_apply_free_function)
|
||||
{
|
||||
etl::tuple<int, int, int> t(1, 2, 3);
|
||||
|
||||
CHECK_EQUAL(6, etl::apply(apply_sum, t));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_apply_function_object)
|
||||
{
|
||||
etl::tuple<int, int> t(10, 20);
|
||||
|
||||
CHECK_EQUAL(30, etl::apply(Summer(), t));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
TEST(test_apply_lambda)
|
||||
{
|
||||
etl::tuple<int, int, int> t(2, 3, 4);
|
||||
|
||||
int result = etl::apply([](int a, int b, int c) { return a * b * c; }, t);
|
||||
|
||||
CHECK_EQUAL(24, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_apply_member_function)
|
||||
{
|
||||
Accumulator acc = {0};
|
||||
|
||||
etl::apply(&Accumulator::add, etl::make_tuple(&acc, 5, 7));
|
||||
|
||||
CHECK_EQUAL(12, acc.total);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_apply_rvalue_tuple)
|
||||
{
|
||||
CHECK_EQUAL(6, etl::apply(apply_sum, etl::make_tuple(1, 2, 3)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP11
|
||||
TEST(test_apply_empty_tuple)
|
||||
{
|
||||
etl::tuple<> t;
|
||||
|
||||
int result = etl::apply([]() { return 42; }, t);
|
||||
|
||||
CHECK_EQUAL(42, result);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user