2011-01-14 8 views
68

Stavo sperimentando con C++ 0x modelli variadic quando sono incappato in questo problema:È possibile "archiviare" un pacchetto di parametri del modello senza espanderlo?

template < typename ...Args > 
struct identities 
{ 
    typedef Args type; //compile error: "parameter packs not expanded with '...' 
}; 

//The following code just shows an example of potential use, but has no relation 
//with what I am actually trying to achieve. 
template < typename T > 
struct convert_in_tuple 
{ 
    typedef std::tuple< typename T::type... > type; 
}; 

typedef convert_in_tuple< identities< int, float > >::type int_float_tuple; 

GCC 4.5.0 mi dà un errore quando provo a typedef il pacco parametri di modello.

In sostanza, mi piacerebbe "memorizzare" il pacchetto di parametri in un typedef, senza decomprimerlo. È possibile? Se no, c'è qualche ragione per cui questo non è permesso?

risposta

50

Un altro approccio, che è leggermente più generico di Ben, è la seguente:

#include <tuple> 

template <typename... Args> 
struct variadic_typedef 
{ 
    // this single type represents a collection of types, 
    // as the template arguments it took to define it 
}; 

template <typename... Args> 
struct convert_in_tuple 
{ 
    // base case, nothing special, 
    // just use the arguments directly 
    // however they need to be used 
    typedef std::tuple<Args...> type; 
}; 

template <typename... Args> 
struct convert_in_tuple<variadic_typedef<Args...>> 
{ 
    // expand the variadic_typedef back into 
    // its arguments, via specialization 
    // (doesn't rely on functionality to be provided 
    // by the variadic_typedef struct itself, generic) 
    typedef typename convert_in_tuple<Args...>::type type; 
}; 

typedef variadic_typedef<int, float> myTypes; 
typedef convert_in_tuple<myTypes>::type int_float_tuple; 

int main() 
{} 
+0

Bello, molto simile a quello provato in origine dall'OP. –

+1

Soluzione eccellente, non ho pensato di utilizzare la specializzazione parziale dei modelli! –

+0

@GMan: domanda veloce ...questo è stato utile, ma deve la versione parzialmente specializzata in realtà essere 'typedef typename convert_in_tuple tipo :: tipo;', o se questo non ha importanza? – Jason

8

Penso che il motivo per cui non è consentito è che sarebbe disordinato e si può aggirare. È necessario utilizzare l'inversione di dipendenza e rendere la struttura che memorizza il pacchetto di parametri in un modello di fabbrica in grado di applicare quel pacchetto di parametri a un altro modello.

Qualcosa sulla falsariga di:

template < typename ...Args > 
struct identities 
{ 
    template < template<typename ...> class T > 
    struct apply 
    { 
     typedef T<Args...> type; 
    }; 
}; 

template < template<template<typename ...> class> class T > 
struct convert_in_tuple 
{ 
    typedef typename T<std::tuple>::type type; 
}; 

typedef convert_in_tuple< identities< int, float >::apply >::type int_float_tuple; 
+0

Ho provato il tuo codice su GCC 4.5, hai solo bisogno di cambiare 'typename T' in' class T' e cambiare il parametro 'convert_in_tuple' per essere un parametro template template template:' template