Question

J'ai vu ce joli graphique qui classe qui contenant STL Conviendrait basé sur des exigences différentes de données telles que:

- Taille fixe Vs taille variable

- Les données de même Tyme Vs type différent

- Ordonné Vs données non triées

- Vs séquentielle accès aléatoire

http://plasmahh.projectiwear.org/cce_clean.svg

Je remarque dans cette image, que la STL de C il n'y a pas de conteneur qui est

  1. Taille variable
  2. Hétérogène (données de différents types).

Ne pas C ++ avoir quelque chose pour cela?

PS -. Il peut y avoir beaucoup de permutations fait les différentes propriétés des conteneurs et bien d'autres encore pourraient ne pas être fournis en LIST

Était-ce utile?

La solution

Et bien général dans des conteneurs C ++ sont conçus pour des objets de maintien d'un seul type en utilisant des modèles. Si vous voulez différents types qui sont tous dérivés d'un type que vous pouvez stocker un conteneur de pointeurs (je suppose que vous pourriez aussi avoir un récipient de vide * à quoi que ce soit ...), par exemple std :: vector .

Si vous voulez des types complètement indépendants, vous pouvez stocker des objets qui peuvent en toute sécurité les autres types faire référence, comme boost :: tout.

http://www.boost.org/doc/ libs / 1_47_0 / doc / html / any.html

Quelques exemples en dehors du site de boost:

#include <list>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::list<boost::any> many;

void append_int(many & values, int value)
{
    boost::any to_append = value;
    values.push_back(to_append);
}

void append_string(many & values, const std::string & value)
{
    values.push_back(value);
}

bool is_int(const boost::any & operand)
{
    return operand.type() == typeid(int);
}
bool is_char_ptr(const boost::any & operand)
{
    try
    {
        any_cast<const char *>(operand);
        return true;
    }
    catch(const boost::bad_any_cast &)
    {
        return false;
    }
}

boost :: variante est similaire, mais vous spécifiez tous les types autorisés, au lieu de laisser tout type dans votre récipient.

http://www.boost.org/doc/ libs / 1_47_0 / doc / html / variant.html

std::vector< boost::variant<unsigned, std::string> > vec;
vec.push_back( 44);
vec.push_back( "str" );
vec.push_back( SomthingElse(55, 65) ); //not allowed

Autres conseils

Le principe de base dans la bibliothèque standard est que les « conteneurs » sont homogènes; la norme C ++ ne tient pas compte des choses comme std::pair ou std::tuple à être des conteneurs. (Je considérerais le graphique trompeur, car il ne les considère comme des conteneurs.) Si vous avez besoin d'un conteneur hétérogène, il faudrait utiliser un conteneur de boost::variant, ou quelque chose dans ce sens.

std::pair et std::tuple sont à peine C ++ conteneurs .... donc pas, il n'y a pas des conteneurs hétérogènes dans la STL, car il n'est pas nécessaire de les avoir intégrés.

Il existe plusieurs méthodes pour créer de tels conteneurs. L'approche que je recommande sont:

  • polymorphisme en utilisant
  • en utilisant un type de variante

Pour Polymorphisme, vous pouvez consulter Boost pointeur conteneur bibliothèque.

boost::ptr_vector<Base> vec;
vec.push_back(new Derived);
vec.push_back(new Derived2);

Il imite les conteneurs STL, mais fournit des fonctionnalités orientées vers le polymorphisme:

  • éléments d'accès comme Base&
  • Gestion automatique de la mémoire
  • comportement de copie spécifique (en utilisant des méthodes de new_clone)
  • sucre Syntactic: boost::ptr_vector<Base>::iterator it; donné, *it est un Base&

Si vos types ne sont pas liés, l'autre possibilité est d'utiliser Variante Boost . Fondamentalement, une variante est similaire à:

enum { Type1, Type2, ... } _type;
union {
  SomeType1 _1;
  SomeType2 _2;
  ...
} _u;

Bien sûr, depuis sa poussée, il offre des garanties spécifiques pour vous assurer que vous ne pouvez accéder aux membres du syndicat qui est actuellement actif et soulève la restriction sur les classes avec les constructeurs / destructeurs ne pas être utilisables dans les syndicats traditionnels.

Il fournit également des installations, comme le static_visitor, qui est l'équivalent d'un interrupteur du type, et fera l'erreur de compilation si l'un des états possibles ne se visite pas.

Une bibliothèque qui n'a pas encore accepté dans Boost. Mais qui a été proposé pour inclusion est ciblée vers ceci:

http://rawgit.com/joaquintides/poly_collection/website /doc/html/index.html

Il fournit une classe nommée belle any_collection qui permet d'avoir un conteneur hétérogène via boost :: type_erasure :: tout: http: // rawgit. com / joaquintides / poly_collection / site web / doc / html / poly_collection / tutorial.html # poly_collection.tutorial.basics.boost_any_collection

Sinon, en C ++ 17 il y a moyen simple de mettre en œuvre ceci: https://gieseanw.wordpress.com / 2017/05/03 / un-vrai-conteneur hétérogène en c /

mentionnant l'exemple de l'article précité:

namespace andyg{
struct heterogeneous_container{
private:
    template<class T>
    static std::unordered_map<const heterogeneous_container*, std::vector<T>> items;
public:
    template <class T>
    void push_back(const T& _t)
    {
        items<T>[this].push_back(_t);
    }
};

// storage for our static members
template<class T>
std::unordered_map<const heterogeneous_container*, std::vector<T>> heterogeneous_container::items;
} // andyg namespace

Ensuite, utilisable facilement:

andyg::heterogeneous_container c;
c.push_back(1);
c.push_back(2.f);
c.push_back('c');
struct LocalStruct{};
c.push_back(LocalStruct{});

L'auteur affirme qu'il est une mise en œuvre du jouet, mais je pense que cela est vraiment un moyen intelligent pour la mettre en œuvre, et a un avantage de simplicité sur poly_collection ou un vecteur de variantes.

La taille fixe (comme des conteneurs hétérogènes std::tuple exigent que les types soient connus au moment de la compilation. Si vous souhaitez effectuer une taille variable contenant hétérogène, il suffit de faire un std::vector<std::tuple<T1,T2,...,TN>>.

Si vous voulez un conteneur hétérogène où les types ne sont pas connus au moment de la compilation (si ce serait variable ou fixe taille) vous devrez pointeurs de magasin (ou pointeurs intelligents) à un type de base connue au moment de la compilation, ou alternativement envisager quelque chose comme un récipient de boost::any. La STL ne fournit pas directement un tel récipient soit dimensionné fixe ou variable avec des éléments hétérogènes déterminés au moment de l'exécution.

Si l'élément que vous stockez serait boost::any ou boost::variant vous pouvez indirectement stocker des données hétérogènes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top