2

Getting inspiration from this question, I managed to implement a function which takes two tuples as input and return a tuple which components are the min of each components of the tuples given in input.

template<typename T, T...>
struct integer_sequence { };

template<std::size_t N, std::size_t... I>
struct gen_indices : gen_indices<(N - 1), (N - 1), I...> { };
template<std::size_t... I>
struct gen_indices<0, I...> : integer_sequence<std::size_t, I...> { };

template <typename ... T, std::size_t ... I>
std::tuple<T...> min_tuple_impl(
        const std::tuple<T...>& t1,
        const std::tuple<T...>& t2,
        integer_sequence<std::size_t, I...>)
{
    return { (std::min(std::get<I>(t1), std::get<I>(t2)))... };
}

template <typename ... T>
std::tuple<T...> min_tuple(
        const std::tuple<T...>& t1,
        const std::tuple<T...>& t2)
{
    return min_tuple_impl(t1, t2, gen_indices<sizeof...(T)>{});
}

Now, I would like it to work on all components but the last one.

std::tuple<int, int, int> t1 {10, 20, 30}
std::tuple<int, int, int> t2 {15, 15, 15}
min_tuple(t1, t2) // == {10, 15, 30}, for the last one, always keep the component of t1

How could I get this in C++11?

max66
  • 65,235
  • 10
  • 71
  • 111
fontanf
  • 209
  • 1
  • 6
  • Cannot reproduce: from `auto t3 = min_tuple(t1, t2);` I get a tuple with 10, 15 and 15. – max66 May 06 '21 at 22:30
  • @max66 yes, that's the point. Currently, I get {10, 15, 15} but I would like to get {10, 15, 30}. I want the last component to remain the last component of t1 and not the min of the last components of t1 and t2 – fontanf May 06 '21 at 23:17
  • Sorry: I've misunderstood. Answer added. – max66 May 07 '21 at 00:32

1 Answers1

1

Now, I would like it to work on all components but the last one.

for the last one, always keep the component of t1

So, to solve this, pass a reduced list of integers (not sizeof...(T) but sizeof...(T)-1u):

template <typename ... T>
std::tuple<T...> min_tuple(
        const std::tuple<T...>& t1,
        const std::tuple<T...>& t2)
{
    return min_tuple_impl(t1, t2, gen_indices<sizeof...(T)-1u>{});
} // .....................................................^^^

At the end, add the last t1 element:

template <typename ... T, std::size_t ... I>
std::tuple<T...> min_tuple_impl(
        const std::tuple<T...>& t1,
        const std::tuple<T...>& t2,
        integer_sequence<std::size_t, I...>)
{
    return { (std::min(std::get<I>(t1), std::get<I>(t2)))..., 
              std::get<sizeof...(I)>(t1) };
} // .........^^^^^^^^^^^^^^^^^^^^^^^^^^

Caution: You have to be sure that sizeof...(T) is strictly greater than zero.

max66
  • 65,235
  • 10
  • 71
  • 111