2016-05-13 22 views
7

Sto utilizzando i pacchetti di parametri variadic per la progettazione della classe basata su criteri.Pacchetto parametri variabile multiplo per modello Classe

template <APITypes APIType, class... Policies> 
class IShader : public Policies... { 

}; 

I criteri vengono definiti quando chiamati o con valori predefiniti se nessuno è specificato. Il problema nasce quando ho bisogno di aggiungere un altro parametro pacchetto variadic:

template <AttributeType... Attributes, APITypes APIType, class... Policies> 
class IShader : public Policies... { 

}; 

Ciò genera l'errore "Parametro Template Pack deve essere l'ultimo parametro di modello". Sto pensando di utilizzare il pacchetto di attributi per modificare il comportamento di almeno una delle politiche. Ma non riesco a capire come ottenere due pacchetti di parametri variadici in una classe template.

+1

Non è possibile. È necessario ripensare il modello/design della classe. –

+1

Neanche con una sorta di indirezione? Dì un wrapper di qualche tipo per la lista degli attributi. O modelli di modelli? – James

+6

Si può sempre considerare qualcosa come 'IShader , APITipo, Politiche >' – chris

risposta

5

Nei commenti di discussione si è espressa la volontà di considerare una sorta di riferimento indiretto, o "un involucro di qualche tipo per l'elenco degli attributi".

Un leggero std::tuple basata su involucro, insieme con la specializzazione, potrebbe funzionare qui:

template <typename attribute_tuple, APITypes APIType, 
      typename policy_tuple> class IShader; 

template <AttributeType... Attributes, APITypes APIType, 
      class... Policies> 
class IShader<std::tuple<Attributes...>, APIType, 
       std::tuple<Policies...>> : public Policies... { 

// ... 

}; 

L'obiettivo qui è quello di utilizzare un'istanza modello sulla falsariga di:

IShared<std::tuple<Attribute1, Attribute2>, APITypeFoo, 
     std::tuple<Policy1, Policy2>> ishared_instance; 

e incrocia le dita che questo sta andando a corrispondere alla dichiarazione modello speciale, a quel punto entrambi i pacchetti di parametri sono disponibili per la specializzazione del modello da utilizzare, singolarmente.

+0

Le tuple sono necessarie quando si dichiarano oggetti della classe IShader? – James

+0

@James Le tuple sono necessarie, ma solo come tipo. Nessuna tupla viene in realtà creata. – md5i

+0

Anche qui 'IShared , APITypeFoo, std :: tuple > ishared_instance;'? Non sarà allora non usare la specializzazione che fornisce l'implementazione, ma piuttosto il default. Non potresti usare la classe come questo 'IShared ishared_instance;'? – James

6

Penso che la risposta più semplice sia creare wrapper di tipo di modello per i propri pacchetti di parametri. Per esempio:

template <AttributeType... T> 
struct Attributes {}; 

template <typename... T> 
struct Policies {}; 

Quindi è possibile dichiarare il tipo di IShader:

template <typename... T> 
class IShader; 

Creare la realizzazione di una specializzazione. Nota che in una specializzazione puoi avere più argomenti per i parametri.

template <AttributeType... AttributeList, ApiTypes APIType, typename... PolicyList> 
class IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>> 
    : public PolicyList... 
{ 
    ... 
}; 

Poi si può anche consentire all'utente di specificare gli argomenti in ordine diverso (assicuratevi di inoltrare i costruttori se farlo in questo modo attraverso l'ereditarietà):

template <AttributeType... AttributeList, ApiTypes APIType, typename... PolicyList> 
struct IShader<ApiType, Policies<PolicyList...>, Attributes<AttributeList...> 
    : public IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>> 
{ 
    using IShader<Attributes<AttributeList...>, ApiType, Policies<PolicyList...>>::IShader; 
}; 

Se sei stato davvero immaginazione, puoi anche usare trucchi per metaprogrammazione per consentire gli argomenti in qualsiasi ordine senza enumerare tutti gli ordini. Questo è lasciato come un esercizio al lettore. :)

Problemi correlati