Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to apply a generic function over tuple elements?

Tags:

c++

c++11

c++14

I have found a for_each loop for tuples which just iterates over the elements and passes them into a function.

namespace std {
  template<int I, class Tuple, typename F> struct for_each_impl {
    static void for_each(const Tuple& t, F f) {
      for_each_impl<I - 1, Tuple, F>::for_each(t, f);
      f(get<I>(t));
    }
  };
  template<class Tuple, typename F> struct for_each_impl<0, Tuple, F> {
    static void for_each(const Tuple& t, F f) {
      f(get<0>(t));
    }
  };
  template<class Tuple, typename F>
  void for_each(const Tuple& t, F f) {
    for_each_impl<tuple_size<Tuple>::value - 1, Tuple, F>::for_each(t, f);
  }
}

.

auto t = std::make_tuple(Foo(),Bar(),Baz());
std::for_each(t,[](???){});

Would it be possible to have a generic function like this?

std::for_each(t,[](T &&t){t.foo();});

In the end I just want to have something that works with every tuple.

std::get<0>(t).foo();
std::get<1>(t).foo();
std::get<2>(t).foo();
...

Maybe this would be easier with macros?

like image 576
Maik Klein Avatar asked Nov 16 '14 17:11

Maik Klein


1 Answers

In c++14 you can use a generic lambda expression:

for_each(t, [] (auto&& t) { std::forward<decltype(t)>(t).foo(); });

In c++11 you can declare your own functor:

struct Lambda
{
    template <typename T>
    void operator()(T&& t) const { std::forward<T>(t).foo(); }
};

for_each(t, Lambda{});

or if, instead, you would like to apply a different function depending on the tuple element's type currently being processed, then once again a custom functor is the way to go:

struct Lambda
{
    void operator()(const Foo& foo) const { foo.foo(); }
    void operator()(const Bar& bar) const { bar.bar(); }
    void operator()(const Baz& baz) const { baz.baz(); }
};

for_each(t, Lambda{});

And as a side note: do not define functions inside the std namespace.

like image 151
Piotr Skotnicki Avatar answered Oct 15 '22 16:10

Piotr Skotnicki