Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Result type of applying polymorphic function to each tuple element

Tags:

c++

tuples

c++14

I'm trying to write a transform function for tuples, however all examples I found either apply a function to tuple elements passed by reference or use non-unary functions.

I however would like to have something like

std::tuple<float, int> t(3.f, 2);
// returns std::tuple<bool, bool>:
auto r1 = transform(t, [] (auto v) { return v > decltype(v)(2); });
// returns std::tuple<float, int>:
auto r2 = transform(t, [] (auto v) { return v + decltype(v)(1); });

The question I got regarding this is: Is it possible to determine the result type of applying an unary function to each tuple element?

like image 202
Richard Vock Avatar asked Jan 04 '14 17:01

Richard Vock


1 Answers

Let std::make_tuple do the type inference for you. You do need an index_sequence pack expansion to build the make_tuple call:

template <typename T, typename F, std::size_t... I>
auto tmap(T&& t, F&& f, std::index_sequence<I...>) {
  return std::make_tuple(f(std::get<I>(std::forward<T>(t)))...);
}

template <typename T, typename F>
auto tmap(T&& t, F&& f) {
  return tmap(std::forward<T>(t),
              std::forward<F>(f),
              std::make_index_sequence<
                std::tuple_size<
                  typename std::decay<T>::type
                >::value>{});
}

C++11-compatible demo at Coliru.

Note that the returned tuple will store a value when f returns a reference type. If you actually want to store references you need the more complicated helper function:

template <typename T, typename F, std::size_t... I>
auto tmap(T&& t, F&& f, std::index_sequence<I...>) {
  return std::tuple<decltype(f(std::get<I>(std::forward<T>(t))))...>{
    f(std::get<I>(std::forward<T>(t)))...
  };
}
like image 159
Casey Avatar answered Sep 28 '22 05:09

Casey