2014-10-17 17 views
10

Supponiamo che io ho una classe con la seguente firma:In che modo enable_if una classe con argomenti modello variadic?

template <typename T, typename... Args> 
class A; 

Ma come questo si comporta classe dovrebbero dipendere da qualche altro parametro, diciamo che è il valore di T::value:

template <typename T, typename... Args, typename Enable> 
class A; 

template <typename T, typename... Args, typename = typename std::enable_if<T::value>::type> 
class A 
{ 
    // do something 
}; 

template <typename T, typename... Args, typename = typename std::enable_if<!T::value>::type> 
class A 
{ 
    // do something else 
}; 

int main() { return 0; } 

Tuttavia, questo programma ha pronunciato la seguente errore:

prog.cpp:6:11: error: parameter pack ‘Args’ must be at the end of the template parameter list class A;

ho faticato a trovare una buona fonte di informazioni sull'uso di 012.per selezionare classi con modelli variadic. L'unica domanda che ho trovato è questo:

How to use std::enable_if with variadic template

Ma, nonostante il nome, questa domanda e le sue risposte non sono molto aiuto. Se qualcuno potrebbe fornire o collegare una guida su come questo dovrebbe essere affrontato e perché sarebbe apprezzato.

risposta

8

Prima di tutto, ciò che si sta cercando è la scrittura più definizioni di un modello di classe. Questo non è permesso perché viola una regola di definizione. Se si desidera eseguire l'abilitazione condizionale con le classi, sono necessarie le specializzazioni . Inoltre, il messaggio di errore del compilatore ti ha già detto che non puoi avere un pacchetto di parametri variadic nel mezzo di un elenco di parametri.

Un modo per farlo sarebbe:

namespace detail { 

template<typename T, typename Enable, typename... Args> 
class A_impl; 

template<typename T, typename... Args> 
class A_impl<T, typename std::enable_if<T::value>::type, Args...> { 
    // code here 
}; 

template<typename T, typename... Args> 
class A_impl<T, typename std::enable_if<!T::value>::type, Args...> { 
    // code here 
}; 
} 

template<typename T, typename...Args> 
class A : public detail::A_impl<T, void, Args...> {}; 

Jonathan's way è anche perfettamente bene se la condizione è in realtà un bool, ma potrebbe non essere utile se si desidera aggiungere ulteriori specializzazioni che ogni dipenderà da diversi conditons.

+0

Ho provato a dichiarare 'A a;', ma il compilatore continuava a dirmi: "istanziazione implicita di template non definito" detail :: A_impl 'Apprezzerei molto se riesci a spiegarlo un po '. (Scusa, sto ancora imparando queste cose) – astroboylrx

+0

@astroboylrx Per far funzionare questo, il primo digitare la lista dei parametri del template di 'A' deve avere un membro' value', perché il check-in 'enable_if' dipende da questo.Abbiamo usato' float' invece. Senza il membro 'value', i controlli in' enable_if' non sono validi, quindi il modello principale di 'A_impl' (non ha implementazione, è solo dichiarato) viene selezionato e si ottiene l'errore. – jrok

+0

Ci scusiamo per la mia risposta in ritardo. Grazie per questa spiegazione. Ora lo vedo. :-) – astroboylrx

9

Sembra che per i vostri scopi non è necessario per attivare/disattivare la classe, è sufficiente una specializzazione parziale:

template <typename T, bool B = T::value, typename... Args> 
    class A; 

template <typename T, typename... Args> 
    class A<T, true, Args...>; 

template <typename T, typename... Args> 
    class A<T, false, Args...>; 
+1

Quindi devi fornire 'B' manualmente quando fornisci' Args' ... – Jarod42

+3

Penso che l'utilizzo di [alias modello come qui] (http://coliru.stacked-crooked.com/a/524efebedc6a4d1c) sia più vicino a ciò che OP vuole –

+0

Sì, è semplice racchiuderlo in un alias per renderlo più user-friendly –

Problemi correlati