0

I have created next tuple

std::tuple<double, double, double> m_size = std::make_tuple(1.0, 1.0, 1.0);

I need to multiply every elements of tuple to a coeff equals 2.0 and to get a result like

(2.0,2.0,2.0)

I can do it like so

   std::get<0>(m_size) *= 2.0;
   std::get<1>(m_size) *= 2.0;
   std::get<2>(m_size) *= 2.0;


What other options exist to do same thing?

Alexcei Shmakov
  • 2,203
  • 3
  • 19
  • 34

2 Answers2

2

You're going to have to multiply each element, but something like this will ease the need to std::get on each element manually and multiply, and give the compiler a good chance to optimize.

#include <iostream>
#include <type_traits>
#include <tuple>
#include <iomanip>

template <typename T,typename Tuple, size_t... Is>
void multiply_tuple_elements(T coeff, Tuple& tuple,std::index_sequence<Is...>)
{
    using do_= int[];
    (void)do_{0, ( 
            std::get<Is>(tuple)*=coeff
    ,0)...}; 
}

int main()
{
    double coeff = 2.0;
    std::tuple<double, double, double> m_size = std::make_tuple(1.0, 1.0, 1.0);
    multiply_tuple_elements(
            coeff,
            m_size ,
            std::make_index_sequence<std::tuple_size<decltype(m_size)>::value>()
    );

    std::cout << std::fixed;
    std::cout << std::get<0>(m_size) << std::endl;
    std::cout << std::get<1>(m_size) << std::endl;
    std::cout << std::get<2>(m_size) << std::endl;

    return 0;
}

Demo

rmawatson
  • 1,909
  • 12
  • 20
0

How can I do this more efficiently?

In sense of execution performance: You cannot... Every multiplication will involve the FPU of your CPU, and every multiplication needs to be done separately there.

If you want to get simpler code (that, once compiled, still does the multiplications separately...), you might try to implement some kind of for_each for tuples, possibly based on this answer, such that you could write a one-liner like this:

foreach(m_size, [](double& v) { v *= 2; });

Not sure if this fits your definition of efficiency, though...

As types are all the same, you could switch to a std::array<double, 3> and then use standard libraries std::for_each instead. This could even be further simplified by providing range-based wrappers (unfortunately not yet existing in standard library):

template <typename C, typename F>
void for_each(C& c, F&& f)
{
    std::for_each(c.begin(), c.end(), std::move(f));
}
Aconcagua
  • 24,880
  • 4
  • 34
  • 59