在没有递归的情况下为一个对象上的每个元组元素调用函数

Ria*_*iaD 3 c++ tuples variadic-templates c++14

我有一个类的对象A,可以使用不同的类型调用,并在每次调用时返回自我更改.出于这个问题的目的,这样A

struct A {
    A call(const int&) {
    }
    A call(const string& s) {
    }
    ////
} a;
Run Code Online (Sandbox Code Playgroud)

所以我有一个未知类型的元组:

std::tuple<Types...> t;
Run Code Online (Sandbox Code Playgroud)

我想a用每个元组元素调用,所以我希望得到类似的东西:

b = a;
b = b.call(get<0>(t));
b = b.call(get<1>(t));
b = b.call(get<2>(t));
//...
Run Code Online (Sandbox Code Playgroud)

要么

b = a.call(get<0>(t)).call(get<1>(t)).call(get<2>(t)...)
Run Code Online (Sandbox Code Playgroud)

订单并不是很重要(我的意思是,如果呼叫顺序被颠倒甚至改组,那就没关系).

我确实理解它可以用递归但它很难看.是否有可能在没有递归的情况下实现?

Jar*_*d42 10

您可以使用std::index_sequence<Is...>,例如:

namespace detail
{

    template <std::size_t...Is, typename T>
    void a_call(A& a, std::index_sequence<Is...>, const T& t)
    {
        int dummy[] = {0, ((a = a.call(std::get<Is>(t))), void(), 0)...};
        static_cast<void>(dummy); // Avoid warning for unused variable.
    }

}

template <typename ... Ts>
void a_call(A& a, const std::tuple<Ts...>& t)
{
    detail::a_call(a, std::index_sequence_for<Ts...>{}, t);
}
Run Code Online (Sandbox Code Playgroud)

在C++ 17中,Folding表达式允许:

    template <std::size_t...Is, typename T>
    void a_call(A& a, std::index_sequence<Is...>, const T& t)
    {
        (static_cast<void>(a = a.call(std::get<Is>(t))), ...);
    }
Run Code Online (Sandbox Code Playgroud)

甚至,用std::apply:

template <typename ... Ts>
void a_call(A& a, const std::tuple<Ts...>& t)
{
    std::apply([&](const auto&... args){ (static_cast<void>(a = a.call(args)), ...); }, t);
}
Run Code Online (Sandbox Code Playgroud)