在C ++ 17/20中遍历元组

时间:2019-02-11 22:59:42

标签: c++ tuples c++17

有人知道用C ++ 17/20遍历元组的好方法吗?假设我们有一些这样的代码:

class Test
{
    public:
        Test( int x ) : x_(x) {};
        void Go() const { std::cout << "Hi!" << x_ << "\n" ; }
        int x_;
};
int main()
{
    std::tuple tplb{ Test{1} , Test{2} ,  Test{3} };
}

如何使用最新的17/20功能遍历元组并在每个元组上调用Go()方法?

我知道您可以只得到对象的向量,然后它很容易工作。我的目标是能够拥有某种多态性而不必使用虚函数。

该想法将是能够在元组中具有支持相同方法的其他对象类型。如果该方法存在于每个对象中,则代码将无需使用基类,虚函数,vtable等进行编译和执行。

std::applystd::invoke是否有某种方法?

2 个答案:

答案 0 :(得分:1)

  

std :: apply或std :: invoke是否有某种方法?

std::apply确实符合折叠表达式的要求:

std::tuple tplb{ Test{1} , Test{2} ,  Test{3} };

std::apply([](const auto&... tests){(tests.Go(), ...);}, tplb);

在这里,我们为Go()的每个类型值调用方法tuple

  

该想法将是能够在元组中具有支持相同方法的其他对象类型。如果该方法存在于每个对象中,则代码将无需使用基类,虚函数,vtable等进行编译和执行。

因此上述方法有效。 您可以根据类型进一步分配到不同的实现,也可以使用std::visit's example中的overloaded类:

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

auto f = overloaded {
        [](const Test& test) { test.Go(); },
        [](double arg) { std::cout << d << ' '; },
        [](const std::string& arg) { std::cout << arg << ' '; },
    };
std::apply([&](const auto&... e){ (overloaded(e), ...);}, my_tuple);

答案 1 :(得分:0)

需要std::index_sequence技巧的一小部分才能访问元组的每个成员。

#include <iostream>
#include <tuple>
#include <utility>

class Test
{
    public:
        Test( int x ) : x_(x) {}; 
        void Go() const { std::cout << "Hi!" << x_ << "\n" ; } 
        int x_; 
};



template<typename F, typename T, std::size_t... Index>
void doStuffIndex(F&& action, T const& tup, std::index_sequence<Index...> const&)
{
    bool ignore[] = {((std::get<Index>(tup).*action)(), true)...};
}

template<typename F, typename... Obj>
void doStuff(F&& action, std::tuple<Obj...> const& tup)
{
    doStuffIndex(action, tup, std::make_index_sequence<sizeof...(Obj)>());
}

int main()
{
    std::tuple<Test, Test, Test> tplb{ Test{1} , Test{2} ,  Test{3} };
    doStuff(&Test::Go, tplb);
}