Question

Je dois créer une carte, des entiers à des ensembles de tuples, les tuples dans un seul ensemble ont la même taille. Le problème est que la taille d'un tuple et ses types de paramètres peut être déterminé lors de l'exécution, pas la compilation. J'imagine quelque chose comme:

std::map<int, std::set<boost::tuple> >

mais pas exctly sûr de savoir comment faire exactement cela, en utilisant des pointeurs bossibly.

Le but est de créer des relations temporaires (tables), chacun avec un identifiant unique (clé), peut-être vous avez une autre approche.

Était-ce utile?

La solution

Le but de boost::tuple est de mélanger les types arbitraires. Si, comme vous le dites,

  

Je ne fais que des entiers INSERTION DE

vous devez utiliser map< int, set< vector< int > > >. (Si je vous, je jette quelques typedefs à ce sujet.)

Pour répondre à la question initiale, cependant, ne permet pas boost::tuple types arbitraires à l'exécution. boost::any fait. Cependant, any ne supporte pas la comparaison donc il y a un peu plus de travail si vous voulez l'utiliser dans un set.

typedef vector< boost::any > tuple;
struct compare_tuple { bool operator()( tuple const &l, tuple const &r ) const {
    assert ( l.size() == r.size() );

    for ( tuple::iterator lit = l.begin(), rit = r.begin();
          lit != l.end(); ++ lit, ++ rit ) {
        assert ( lit->type() == rit->type() );

        if ( lit->type() == typeid( foo ) ) { // find the type and perform "<"
            return boost::any_cast<foo>(*lit) < boost::any_cast<foo>(*rit);
        } else if ( lit->type() == typeid( bar ) ) {
            return boost::any_cast<bar>(*lit) < boost::any_cast<bar>(*rit);
        } /* etc; you will need to enumerate all the types you can insert */
    }
} };

typedef std::map< int, std::set< tuple, compare_tuple > > main_map;

Autres conseils

Comme un côté note moderne (comme les réponses précédentes sont vers 2010), VARIADIC modèles d'aujourd'hui serait utile pour cela:

template<typename... Args> //Accept any number of arguments and types
auto MyFunction(std::tuple<Args...> &T)->void
{
   //Do stuff...
}

Vous ne pouvez stocker ces différents ensembles dans la même collection si vous avez une classe de base commune pour eux. Vous pouvez écrire une interface abstraite, puis mettre en œuvre que pour chaque type de table / tuple. Le problème est que généralement ces interfaces ont tendance à être très compliqué, et il aurait peut-être classe explosion si vous avez plusieurs types de table / tuples. Boost.Any pourrait être utile pour une telle interface (puisque vous devez gérer différents types de données dynamique).

Si les types de paramètres ont quelque chose en commun, saisir que dans une classe de base abstraite et faire tuple contiennent des pointeurs vers cette classe de base:

class MyParamBase {
public:
    virtual int getFoo() = 0;
    virtual void setFoo(int) = 0;
};

std::map<int, std::set<MyParamBase*> > container;

(boost :: tuple omis par souci de concision. Je ne sais pas pourquoi vous avez besoin d'un ensemble de tuples.)

Vous pouvez ensuite déduire les types de paramètres concrets de MyParamBase et de créer et de les insérer dans la carte:

class SomeParam: MyParamBase {
public:
    virtual int getFoo() { ... }
    virtual void setFoo(int a) { ... }
};

std::set<MyParamBase*> some_set;
some_set.insert(new SomeParam());
container[123] = some_set;

Si les types de paramètres ont rien en commun - ne les mettez pas dans le même plan. Il est fort probable qu'ils ne vont pas ensemble.

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