0

I need to define the return types (???? in code) after a sum with 2 parameters pack! My objective is to define a Tuple class (like std::tuple) and to implement for example here, the addition between two tuples of the same length and compatible type), here is a code snippet to understand :

 template<class FirstType, class ... Types>
 class Tuple{
 ....
 template <typename ... OtherTypes>
 const Tuple<????> operator+(Tuple<OtherTypes...>& other) const{...}
 ... 
 }

The problem is that "int + double" should return me a double for example! I looked on the std::common_type side, but I don't see either. A tuple is constructed as follows:

private:
        FirstType m_first ;
        Tuple<Types...> m_next ;

m_first contains the value, and, m_next contains the next tuple by removing a value.

This is my way of storing the different types although there is another way with a hereditary approach. I have another class with a template for the recursive case.

So I don't see how to get the final return type, I have a get function where I used a getHelper<...> structure to return the correct type but here it's different again. I don't want to use AUTO which can cause me problems and which is not magic.

Thank you in advance for your answers.

Example : Tuple<int,double>(3,4.4) + Tuple<double,double>(3.1,3.1) = Tuple<DOUBLE,DOUBLE>(6.5,7.5)

Antholife
  • 3
  • 4

1 Answers1

0

See here for how to elementwise add two tuples https://stackoverflow.com/a/50815600/4117728. The following build on this answer. What is left to add is just to get the common type tuple:

template <typename T1,typename T2>
struct common_tuple;

template <typename...T1,typename...T2>
struct common_tuple< std::tuple<T1...>,std::tuple<T2...>> {
    using type = std::tuple<std::common_type_t<T1,T2>...>;
};

Then the answer linked above can be adjusted to:

namespace internal
{    
    template<typename T,typename S, size_t... Is>
    common_tuple<T,S>::type add_rhs_to_lhs(T& t1, const S& t2, std::integer_sequence<size_t, Is...>)
    {
        return std::make_tuple( (std::get<Is>(t1) + std::get<Is>(t2))... );      
    }
}

template <typename...T,typename...S>
std::tuple<std::common_type_t<T,S>...> operator + (std::tuple<T...> lhs, const std::tuple<S...>& rhs)
{
   return internal::add_rhs_to_lhs(lhs, rhs, std::index_sequence_for<T...>{});
}


int main(int argc, char *argv[])
{
    auto a = std::make_tuple(1,2,4);
    auto b = std::make_tuple(1.0,2.0,4.0);
    auto c = a + b;
    std::cout << std::get<0>(c) << "\n";
    std::cout << std::get<1>(c) << "\n";
    std::cout << std::get<2>(c) << "\n";
}

However, a + b already yields the common type, hence you can simply use auto:

#include <tuple>
#include <iostream>


namespace internal
{    
    template<typename T,typename S, size_t... Is>
    auto add_rhs_to_lhs(T& t1, const S& t2, std::integer_sequence<size_t, Is...>)
    {
        return std::make_tuple( (std::get<Is>(t1) + std::get<Is>(t2))... );      
    }
}

template <typename...T,typename...S>
auto operator + (std::tuple<T...> lhs, const std::tuple<S...>& rhs)
{
   return internal::add_rhs_to_lhs(lhs, rhs, std::index_sequence_for<T...>{});
}


int main(int argc, char *argv[])
{
    auto a = std::make_tuple(1,2,4);
    auto b = std::make_tuple(1.0,2.0,4.0);
    auto c = a + b;
    std::cout << std::get<0>(c) << "\n";
    std::cout << std::get<1>(c) << "\n";
    std::cout << std::get<2>(c) << "\n";
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thank you, I will try this tonight! However I don't understand the difference between common_type and common_type_t, especially here. It also seemed to me that we couldn't provide templates with two parameter packs.. I'll tell you again – Antholife Mar 03 '22 at 14:42
  • @Antholife `common_type_t` is an alias for `common_type::type` – 463035818_is_not_an_ai Mar 03 '22 at 14:44
  • Thanks ! I have a last question, if I have : class C {...} , class B {...}, class A {... C operator + (B example){ C t, return t; } /////////// If we have A + B how to deduce the return type which, here will be C? without using auto ; with trailling type ? but I can't use it. Common_type not work in this case. – Antholife Mar 08 '22 at 16:59