2013-07-30 8 views
5

Diciamo che ho un valore costante (possibilmente di qualche tipo di enum). Diciamo che ho molte classi A, B, D, ecc.Posso utilizzare un numero costante per scegliere una classe in fase di compilazione, possibilmente utilizzando i modelli?

Posso avere qualcosa di simile?

C<1> anInstanceOfA; //This will be of type A 
C<2> anInstanceOfB; //This will be of type B 
C<3> anInstanceOfD; //This will be of type D 

Quindi, è possibile selezionare una classe basata su un numero costante al momento della compilazione?

Il problema generale è che sto provando a selezionare un funtore basato su una tabella, in cui l'indice è un enum. Vorrei evitare il polimorfismo, se possibile.

Modifica: Per questo progetto non posso usare C++ 11, grazie comunque a chi ha risposto in quel contesto, molto interessante sapere comunque.
Edit 2: In generale posso avere più di 2 classi di destinazione, ho curato la mia domanda

+0

Forse leggere sul "modello di fabbrica" ​​ – arne

risposta

8

Utilizzando il LSP e piana C++ 98:

template <int N> class C; 
template <> class C<1> : public A {}; 
template <> class C<2> : public B {}; 
template <> class C<3> : public D {}; 

C<1> anInstanceOfA; 

Da ereditarietà pubblica in C++ soddisfa il IS-A regola, anInstanceOfA sia IS-A oggetto C<1> e IS_AN A oggetto.

+0

Parli una lingua diversa :) ma in effetti questa soluzione è molto elegante! Un paio di link per il mio uso: http://en.wikipedia.org/wiki/Liskov_substitution_principle ... e, non riesco a trovare nulla su IS-A ... – Antonio

+0

Per compilarlo aggiungo per aggiungere '{}' , ottenendo 'template <> classe C <1>: public A {};' ... corretto? – Antonio

+0

@Antonio si è vero. – 0x499602D2

4

Questo è un abbastanza semplice metafunction:

template <int N> 
struct C { 
    typedef typename std::conditional<N == 1,A,B>::type type; 
}; 

Si potrebbe utilizzare questo come C<1>::type foo;.

Se il compilatore C++ supporta 11 alias modello, è possibile semplificare a:

template <int N> 
using C = typename std::conditional<N == 1,A,B>::type; 

e avere il vostro preferito C<1> foo; sintassi.

in puro C++ 03, implementare std::conditional come:

template <bool, typename A, typename> 
struct conditional { 
    typedef A type; 
}; 

template <typename A, typename B> 
struct conditional<false, A, B> { 
    typedef B type; 
}; 
+0

Puoi anche nidificare 'std :: condizionale' per risparmiare spazio. Non commenterò la sua leggibilità oltre la digitazione di ogni typedef separatamente. – rubenvb

+0

Scusate, avrei dovuto specificare (ho ora), non posso usare C++ 11 – Antonio

+2

@Antonio: 'std :: condizionale' non è esattamente difficile da scrivere, attenzione, né la sua implementazione si basa su qualsiasi C++ 11 caratteristiche. – Fanael

11

Questo non è l'unico modo per fare questo, ma spero accettabili per i vostri scopi:

struct A { }; 
struct B { }; 

template <int N> 
struct choices; 

template <> 
struct choices<1> { typedef A type; }; 

template <> 
struct choices<2> { typedef B type; }; 

template <int N> 
using C = typename choices<N>::type; 

Aggiornamento

: per fare lo stesso senza le funzionalità di C++ 11, è necessario creare una classe con C con un tipo di membro typedef uguale all'alias di tipo corrispondente sopra:

template <int N> 
struct C 
{ 
    typedef typename choices<N>::type type; 
}; 

// ... 
C<1>::type anInstanceOfA; 
C<2>::type anInstanceOfB 
+0

Grazie! (+1 ovviamente) Alla fine selezionerò la risposta di MSalters come più compatta, e perché salva il :: type all'istanziazione – Antonio

Problemi correlati