2016-05-13 22 views
7

Używam pakietów parametrów variadic do projektowania klas opartych na regułach.Wiele pakiet parametrów Variadic dla klasy szablonów

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

}; 

Zasady są określane, gdy są wywoływane lub z wartościami domyślnymi, jeśli żadne nie zostały określone. Problem pojawia się, gdy trzeba dodać kolejny pakiet o zmiennej liczbie argumentów parametru:

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

}; 

Powoduje to błąd „parametr szablonu opakowanie musi być ostatnim parametrem szablonu”. Planuję użyć pakietu atrybutów, aby zmienić zachowanie co najmniej jednej z zasad. Ale nie mogę się dowiedzieć, jak uzyskać dwa pakiety parametrów variadic w jednej klasie szablonu.

+1

Nie możesz. Musisz ponownie przemyśleć swój projekt szablonu/klasy. –

+1

Nawet z pewnym niedostrzeganiem? Powiedz o jakimś opakowaniu listy atrybutów. Lub szablony szablonów? – James

+6

Zawsze możesz wziąć pod uwagę coś takiego jak 'IShader , APIType, Zasady >' – chris

Odpowiedz

5

W komentarzach do dyskusji wyraziłeś gotowość do rozważenia jakiegoś rodzaju pośrednictwa lub "opakowania jakiegoś rodzaju dla listy atrybutów".

Lekki std::tuple -na wrapper, wraz ze specjalizacji, może pracować tutaj:

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... { 

// ... 

}; 

Naszym celem jest użycie instancji szablonu wzdłuż linii:

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

I skrzyżować palce, że to będzie pasować do wyspecjalizowanej deklaracji szablonu, w którym to momencie oba pakiety parametrów są dostępne dla indywidualnej specjalizacji szablonu.

+0

Czy potrzebne są krotki podczas deklarowania obiektów klasy IShader? – James

+0

@James Krotki są potrzebne, ale tylko jako typ. Żadne krotki nie są faktycznie tworzone. – md5i

+0

Nawet tutaj 'IShared , APITypeFoo, std :: tuple > ishared_instance;'? Czy nie będzie wtedy używać specjalizacji zapewniającej implementację, ale raczej domyślnej. Czy nie możesz użyć klasy takiej jak: 'IShared ishared_instance;'? – James

6

Myślę, że najprostszą odpowiedzią jest utworzenie wrapperów typu szablonu dla pakietów parametrów. Na przykład:

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

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

Następnie można zadeklarować swój typ IShader:

template <typename... T> 
class IShader; 

stworzyć swoją implementację jako specjalizacji. Zwróć uwagę, że w specjalizacji możesz mieć wiele argumentów związanych z pakietem parametrów.

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

Wtedy można nawet pozwolić użytkownikowi na określenie argumenty w różnej kolejności (upewnij się, że przekazuje konstruktorów jeśli robi to w ten sposób przez dziedziczenie):

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; 
}; 

Jeśli jesteś jest naprawdę fantazyjne, możesz nawet użyć trików metaprogramowania, aby umożliwić argumenty w dowolnej kolejności bez wyliczania wszystkich zamówień. Jest to ćwiczenie dla czytelnika. :)

Powiązane problemy