124 votes

C++ Tuple vs Struct

Y a-t-il une différence entre l'utilisation d'un std::tuple et de données seulement struct ?

typedef std::tuple<int, double, bool> foo_t;

struct bar_t {
    int id;
    double value;
    bool dirty;
}

D'après ce que j'ai trouvé en ligne, j'ai constaté qu'il existe deux différences majeures : la struct est plus lisible, tandis que le tuple possède de nombreuses fonctions génériques qui peuvent être utilisées. Devrait-il y avoir une différence de performance significative ? De même, la présentation des données est-elle compatible entre elles (casted interchangeable) ?

0 votes

Je viens de remarquer que j'avais oublié le moulage question : la mise en œuvre de la tuple est définie par l'implémentation, elle dépend donc de votre implémentation. Personnellement, je no comptez-y.

26voto

wheaties Points 20917

Si vous utilisez plusieurs tuples différents dans votre code, vous pouvez vous en sortir en condensant le nombre de foncteurs que vous utilisez. Je dis cela parce que j'ai souvent utilisé les formes suivantes de foncteurs :

template<int N>
struct tuple_less{
    template<typename Tuple>
    bool operator()(const Tuple& aLeft, const Tuple& aRight) const{
        typedef typename boost::tuples::element<N, Tuple>::type value_type;
        BOOST_CONCEPT_REQUIRES((boost::LessThanComparable<value_type>));

        return boost::tuples::get<N>(aLeft) < boost::tuples::get<N>(aRight);
    }
};

Cela peut sembler exagéré mais pour chaque emplacement dans la structure, je devrais créer un nouvel objet foncteur en utilisant une structure, mais pour un tuple, je change simplement N . Mieux encore, je peux le faire pour chaque tuple au lieu de créer un tout nouveau foncteur pour chaque structure et pour chaque variable membre. Si j'ai N structures avec M variables membres que NxM functeurs j'aurais besoin de créer (pire scénario) qui peut être condensé vers le bas à un petit morceau de code.

Naturellement, si vous optez pour la méthode des Tuple, vous devrez également créer des Enums pour travailler avec eux :

typedef boost::tuples::tuple<double,double,double> JackPot;
enum JackPotIndex{
    MAX_POT,
    CURRENT_POT,
    MIN_POT
};

et boom, votre code est complètement lisible :

double guessWhatThisIs = boost::tuples::get<CURRENT_POT>(someJackPotTuple);

car il se décrit lui-même quand on veut obtenir les éléments qu'il contient.

8 votes

Uh... C++ a des fonctions pointeurs, donc template <typename C, typename T, T C::*> struct struct_less { template <typename C> bool operator()(C const&, C const&) const; }; devrait être possible. L'écrire en toutes lettres est un peu moins pratique, mais on ne l'écrit qu'une fois.

18voto

NoSenseEtAl Points 2342

Tuple a des comparateurs par défaut intégrés (pour == et !=, il compare chaque élément, pour <.<=... compare en premier, si identique compare en second...) : http://en.cppreference.com/w/cpp/utility/tuple/operator_cmp

edit : comme indiqué dans le commentaire l'opérateur C++20 spaceship vous donne un moyen de spécifier cette fonctionnalité avec une (moche, mais toujours juste une) ligne de code.

1 votes

En C++20, il est possible d'y remédier avec un minimum de texte passe-partout en utilisant l'opérateur de vaisseau spatial .

4voto

nightcracker Points 34498

Eh bien, une structure POD peut souvent être (ab)utilisée dans la lecture et la sérialisation de bas niveau de morceaux contigus. Un tuple pourrait être plus optimisé dans certaines situations et supporter plus de fonctions, comme vous l'avez dit.

Utilisez ce qui est le plus approprié à la situation, il n'y a pas de préférence générale. Je pense (mais je ne l'ai pas testé) que les différences de performances ne seront pas significatives. La disposition des données est très probablement incompatible et spécifique à l'implémentation.

3voto

Matthieu M. Points 101624

En ce qui concerne les "fonctions génériques", Boost.Fusion mérite un peu d'amour... et surtout STRUCTURE D'ADAPTATION DE FUSION BOOSTÉE .

Arraché de la page : ABRACADBRA

namespace demo
{
    struct employee
    {
        std::string name;
        int age;
    };
}

// demo::employee is now a Fusion sequence
BOOST_FUSION_ADAPT_STRUCT(
    demo::employee
    (std::string, name)
    (int, age))

Cela signifie que tous les algorithmes de fusion sont désormais applicables à la structure. demo::employee .


EDITAR : En ce qui concerne la différence de performance ou la compatibilité de la mise en page, tuple La mise en page de l'application est définie par l'implémentation et n'est donc pas compatible (et vous ne devez donc pas effectuer de cast entre les deux représentations). get<N> .

16 votes

Je ne pense pas que ce soit la réponse la plus votée. Elle ne répond même pas à la question. La question porte sur tuple et struct s, pas de boost !

0 votes

@G.Samaras : La question est sur la différence entre les tuples et les struct et notamment l'abondance d'algorithmes pour manipuler les tuples contre l'absence d'algorithmes pour manipuler les structs (en commençant par itérer sur ses champs). Cette réponse montre que cet écart peut être comblé en utilisant Boost.Fusion, apportant à struct s autant d'algorithmes qu'il y en a sur les tuples. J'ai ajouté un petit texte sur les deux questions exactes posées.

1voto

Jerry Coffin Points 237758

Il ne devrait pas y avoir de différence de performance (même insignifiante). Au moins dans le cas normal, ils donneront lieu à la même disposition de la mémoire. Néanmoins, il n'est probablement pas nécessaire que le casting entre les deux fonctionne (même si je pense qu'il y a de bonnes chances que cela fonctionne normalement).

4 votes

En fait, je pense qu'il y a une petite différence. A struct doit allouer au moins 1 octet pour chaque sous-objet alors que je pense qu'une tuple peut s'en sortir en optimisant les objets vides. De plus, en ce qui concerne l'emballage et l'alignement, il se pourrait que les tuples aient plus de marge de manœuvre.

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