Tuple di dimensione tipi sconosciuti / parametri
-
19-09-2019 - |
Domanda
ho bisogno di creare una mappa, da interi a insiemi di tuple, le tuple in un unico insieme hanno la stessa dimensione. Il problema è che la dimensione di una tupla e dei suoi tipi di parametri può essere determinato in fase di esecuzione, non di compilazione. Sto immaginando qualcosa di simile:
std::map<int, std::set<boost::tuple> >
ma non exctly sicuro di come fare esattamente questo, bossibly utilizzando i puntatori.
Lo scopo di questo è quello di creare relazioni temporanee (tabelle), ognuna con un identificatore univoco (chiave), forse hai un altro approccio.
Soluzione
Lo scopo è quello di mescolare boost::tuple
tipi arbitrari. Se, come dici tu,
io sto solo inserisco interi
allora dovreste usare map< int, set< vector< int > > >
. (Se fossi in te, mi piacerebbe gettare un po 'a quel typedef
s.)
Per rispondere alla domanda iniziale, però, boost::tuple
non permette tipi arbitrari in fase di esecuzione. boost::any
fa. Tuttavia, any
non supporta il confronto quindi c'è un po 'di lavoro, se si desidera utilizzarlo in 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;
Altri suggerimenti
Come un moderno side-note (come le risposte precedenti sono circa 2010), Modelli variadic di oggi sarebbe utile per questo:
template<typename... Args> //Accept any number of arguments and types
auto MyFunction(std::tuple<Args...> &T)->void
{
//Do stuff...
}
È possibile memorizzare solo questi insiemi differenti nella stessa collezione, se avete qualche classe base comune per loro. Si potrebbe scrivere un'interfaccia astratta, e quindi implementare che per ogni tipo di tabella / tupla. Il problema è, che di solito tali interfacce tendono ad essere molto disordinato, e si dovrebbe forse avere classe di esplosione se si dispone di molti tipi di tavolo / tuple. Boost.Any potrebbe essere utile per tale interfaccia (poiché è necessario per gestire diversi tipi di dati in modo dinamico).
Se i tipi di parametri hanno qualcosa in comune, che cattura in una classe base astratta e rendere la tupla contiene puntatori a questa classe di base:
class MyParamBase {
public:
virtual int getFoo() = 0;
virtual void setFoo(int) = 0;
};
std::map<int, std::set<MyParamBase*> > container;
(boost :: tuple omesse per brevità. Non certo perché è necessario un insieme di tuple.)
È quindi possibile ricavare i tipi di parametri concreti MyParamBase e creare e inserirli nella mappa:
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;
Se i tipi di parametri non hanno nulla in comune - non metterli nella stessa mappa. Molto probabilmente non appartengono insieme.