32 votes

Ajout de tuple par élément

J'ai quelques valeurs dans un tuple, et je suis à la recherche d'ajouter un autre tuple à l'élément de sage. Donc je voudrais fonctionnalité comme ceci:

std::tuple<int,int> a = {1,2};
std::tuple<int,int> b = {2,4};


std::tuple<int,int> c = a + b; // possible syntax 1
a += b; // possible syntax 2
a += {2,4}; // possible syntax 3

D'où la sortie d'un tuple aurait la valeur {3,6}

A regarder de référence du RPC, mais je ne pouvais pas trouver cette fonctionnalité. Il est possible que cette et cette question sont pertinentes, cependant les réponses sont obscurcis par d'autres complexités.

30voto

Vishaal Shankar Points 1505

Vous pouvez également envisager d'utiliser std :: valarray car il permet exactement les choses que vous semblez vouloir.

 #include <valarray>

int main()
{
    std::valarray<int> a{ 1, 2 }, b{ 2, 4 }, c;
    c = a - b; // c is {-1,-2}
    a += b; // a is {3,6}
    a -= b; // a is {1,2} again
    a += {2, 4}; // a is {3,6} again
    return 0;
}
 

11voto

Simon Kraemer Points 344

Vous pouvez utiliser quelque chose comme cela, qui prend en charge tous les trois de votre syntaxe des propositions:

#include <tuple>
#include <utility>

namespace internal
{
    //see: https://stackoverflow.com/a/16387374/4181011
    template<typename T, size_t... Is>
    void add_rhs_to_lhs(T& t1, const T& t2, std::integer_sequence<size_t, Is...>)
    {
        auto l = { (std::get<Is>(t1) += std::get<Is>(t2), 0)... };
        (void)l; // prevent unused warning
    }
}

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

template <typename...T>
std::tuple<T...> operator + (std::tuple<T...> lhs, const std::tuple<T...>& rhs)
{
   return lhs += rhs;
}

Exemple:

http://coliru.stacked-crooked.com/a/27b8cf370d44d3d5

http://coliru.stacked-crooked.com/a/ff24dae1c336b937


J'allais encore nommés les structures dans la plupart des cas. Les Tuples sont rarement le bon choix.

8voto

sasauke Points 301

La solution de @lubgr est satisfaisante pour votre cas d'utilisation spécifique. Je vous propose une solution générique qui fonctionnera pour des tuples de différents types, ainsi que des tuples de tailles différentes (égales).

 #include <tuple>
#include <utility>
#include <iostream>

template<typename... T1, typename... T2, std::size_t... I>
constexpr auto add(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2, 
                   std::index_sequence<I...>)
{
    return std::tuple{ std::get<I>(t1) + std::get<I>(t2)... };
}

template<typename... T1, typename... T2>
constexpr auto operator+(const std::tuple<T1...>& t1, const std::tuple<T2...>& t2)
{
    // make sure both tuples have the same size
    static_assert(sizeof...(T1) == sizeof...(T2));

    return add(t1, t2, std::make_index_sequence<sizeof...(T1)>{});
}
 

J'ai utilisé quelques fonctionnalités C ++ 17 (principalement liées aux modèles) sans lesquelles le code deviendrait un peu plus compliqué. Une amélioration possible serait d'utiliser la sémantique de mouvement.

Évidemment, cela s'applique à la première "syntaxe possible" que vous avez fournie.

3voto

lubgr Points 29224

Voici une définition d'opérateur pour la syntaxe # 1:

 template <class S, class T> std::tuple<S, T> operator + (const std::tuple<S, T>& lhs, const std::tuple<S, T>& rhs)
{
   return std::make_tuple(std::get<0>(lhs) + std::get<0>(rhs), std::get<1>(lhs) + std::get<1>(rhs));
}
 

Les syntaxes # 2 et # 3 ne sont pas possibles sans créer une structure personnalisée, car elles ne peuvent être définies que comme membres des classes sur lesquelles elles opèrent (et vous ne pouvez pas toucher les classes existantes dans l'espace de noms std ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X