2011-10-12 21 views
5

Ho una serie di tipi di relazione con una relazione uno-a-uno, per esempio:Mappa due tipi in fase di compilazione

TypeA ---> Type1 
TypeB ---> Type2 
TypeC ---> Type3 

So che queste relazione al momento della compilazione.

Poi, ho una classe template che dipende da questi due tipi:

template<class T1,class T2> 
class MyClass 
{ 
    T1 foo; 
    T2 bar; 
}; 

Ora, l'utente della mia biblioteca sarà digitare qualcosa di simile:

MyClass<TypeA,Type1> x; 

Questo è scomodo perché non c'è una dipendenza tra i due tipi e dovrebbe essere sufficiente per l'utente specificare solo il primo tipo.

Inoltre, la miscelazione dei due tipi non dovrebbe essere possibile:

MyClass<TypeA,Type2> y; //it should not compile 

Io non sono molto familiare con modello di programmazione meta, ho avuto l'impressione che questo è compito fattibile, ma potrei sbagliarmi.

Il numero di tipi coinvolti è elevato, tuttavia sono felice di eseguire uno script per generare il codice, se necessario.

Sai se è possibile o sto perdendo tempo? Hai qualche idea per indicarmi la giusta direzione?

risposta

6
template<class T> 
struct get_mapped; 

template<> 
struct get_mapped<TypeA>{ 
    typedef Type1 type; 
}; 

// and so on.... 


template<class T> 
class MyClass{ 
    typedef typename get_mapped<T>::type T2; 

    T foo; 
    T2 bar; 
}; 
3

Perché non basta creare un tipo di involucro:

template <typename T1, typename T2> 
struct wrapper 
{ 
    typedef T1 type1; 
    typedef T2 type2; 
}; 

typedef wrapper<TypeA, Type1> TypeX; 
typedef wrapper<TypeB, Type2> TypeY; 
typedef wrapper<TypeC, Type3> TypeZ; 

Poi l'utente dice, MyClass<TypeX>;, e si definiscono:

template <typename T> 
class MyClass 
{ 
    typename T::type1 foo; 
    typename T::type2 bar; 
}; 

Se si vuole evitare l'uso improprio del modello, utilizzare un specializzazione parziale:

template <typename> class MyClass; // undefined 

template <typename S, typename T> 
class MyClass<wrapper<S,T>> 
{ 
    S foo; 
    T bar; 
}; 

Questo approccio può essere facilmente esteso per includere ulteriormente dati in fase di compilazione nella classe wrapper. In alternativa, è possibile utilizzare std::pair con tipi di membro first_type e second_type.

5
template<class T> struct TypeLetter2TypeDigit; 

template<> struct TypeLetter2TypeDigit<TypeA> { typedef Type1 type; }; 
template<> struct TypeLetter2TypeDigit<TypeB> { typedef Type2 type; }; 
template<> struct TypeLetter2TypeDigit<TypeC> { typedef Type3 type; }; 


template<class T1> // Type2 is not needed 
class MyClass 
{ 
    // Type2 is deduced. 
    typedef typename TypeLetter2TypeDigit<T1>::type T2; 
    T1 foo; 
    T2 bar; 
}; 
+0

made alcune correzioni. Vedi se è corretto. (Inoltre, hai davvero bisogno di un nome così lungo? TypeLetter2TypeDigit?? IMHO qualcosa come 'TypeMap' è sufficiente.) – iammilind

+0

@iammilind. Grazie. Il nome lungo è necessario per mostrare ciò che voglio. Tu o OP puoi usare qualsiasi nome. –

Problemi correlati