Распаковка набора кортежей в n-арную функцию - PullRequest
0 голосов
/ 01 февраля 2019

Предположим, у меня есть ряд кортежей, например, из функции zip.Должны ли функции, работающие в этом диапазоне, быть всегда одинарными или существует какое-либо преобразование, которое распаковывает кортеж в аргументы функции.По сути, я хотел бы сделать следующее:

  auto r1 = {1, 2, 3, 4};
  auto r2 = {'a', 'b', 'c', 'd'};
  auto chars = view::zip(r1, r2) | view::transform([](int a, char x) { return x; });

вместо явного использования std :: tie или std :: apply.

1 Ответ

0 голосов
/ 01 февраля 2019

Похоже, что вам действительно нужен адаптер функций, который взрывает аргументы кортежей.Примерно так ( LIVE ):

#include <type_traits>
#include <utility>
#include <range/v3/core.hpp>
#include <range/v3/utility/semiregular.hpp>
#include <range/v3/utility/tuple_algorithm.hpp>

template<class F>
struct decomposed_fn
{
private:
    CONCEPT_ASSERT(ranges::CopyConstructible<F>());
    ranges::semiregular_t<F> f_;

    template<class FF>
    struct caller
    {
        FF &f_;

        template<class... Args>
        RANGES_CXX14_CONSTEXPR auto operator()(Args &&...args)
        RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
        (
            ranges::invoke(f_, std::forward<Args>(args)...)
        )
    };

public:
    decomposed_fn() = default;
    RANGES_CXX14_CONSTEXPR explicit decomposed_fn(F f)
        noexcept(std::is_nothrow_move_constructible<F>::value)
    : f_(std::move(f))
    {}

    template<class T>
    RANGES_CXX14_CONSTEXPR auto operator()(T &&t)
    RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
    (
        ranges::tuple_apply(caller<F>{f_}, std::forward<T>(t))
    )

    template<class T>
    RANGES_CXX14_CONSTEXPR auto operator()(T &&t) const
    RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
    (
        ranges::tuple_apply(caller<F const>{f_}, std::forward<T>(t))
    )
};

template<class F,
    CONCEPT_REQUIRES_(ranges::CopyConstructible<std::decay_t<F>>())>
RANGES_CXX14_CONSTEXPR auto decomposed(F &&f)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
    decomposed_fn<std::decay_t<F>>(std::forward<F>(f))
)

, с помощью которого вы можете сформулировать свой диапазон как:

auto chars = view::zip(r1, r2)
    | view::transform(decomposed([](int, char x) { return x; }));
...