11

Ho una funzione modello variadic che si chiama per determinare il numero più grande in un elenco (costituito dagli argomenti templatizzati). Sto cercando di fare una specializzazione per quando il pacchetto di parametri è vuoto, quindi posso solo restituire il numero in cima all'elenco, ma non so come farlo. Sono solo familiarizzare con i modelli variadic e il modello di specializzazione, ma questo è quello che ho finora:Specializzazione di modelli per un pacchetto di parametri vuoto

#include <string> 
#include <iostream> 

using namespace std; 

template <int N, int... N2> 
int tmax() { 
    return N > tmax<N2...>() ? N : tmax<N2...>(); 
} 

template <int N> 
int tmax() { 
    return N; 
} 

int main() { 
    cout << tmax<32, 43, 54, 12, 23, 34>(); 
} 

Tuttavia, questo produce il seguente errore:

test.cpp: In function ‘int tmax() [with int N = 34, int ...N2 = {}]’: 
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 23, int ...N2 = {34}]’ 
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 12, int ...N2 = {23, 34}]’ 
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 54, int ...N2 = {12, 23, 34}]’ 
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 43, int ...N2 = {54, 12, 23, 34}]’ 
test.cpp:9:45: instantiated from ‘int tmax() [with int N = 32, int ...N2 = {43, 54, 12, 23, 34}]’ 
test.cpp:18:39: instantiated from here 
test.cpp:9:45: error: no matching function for call to ‘tmax()’ 
test.cpp:9:45: error: no matching function for call to ‘tmax()’ 

Ho anche provato questo, basta per vedere se avrebbe funzionato (anche se introduce il numero 0 alla lista in modo casuale in modo che non potrà mai restituire un numero minore di 0):

template <int N, int... N2> 
int tmax() { 
    return N > tmax<N2...>() ? N : tmax<N2...>(); 
} 

template <> 
int tmax<>() { 
    return 0; 
} 

Tuttavia, in aggiunta agli errori di cui sopra, ottengo questo errore:

error: template-id ‘tmax<>’ for ‘int tmax()’ does not match any template declaration 

Così che cosa devo fare per ottenere questo lavoro?

Sto usando g ++ 4.5.2 con il flag -std=c++0x.

risposta

22

Vedo due errori utilizzando clang.

  1. Inserire il sovraccarico in un primo singolo int.

  2. Rendere le cose univoche per gli elenchi di lunghezza 1. Ricordare che le liste variadic possono avere dimensione zero e quando lo fanno, mi sembra che tu abbia un'ambiguità.

Questo compila e funziona correttamente per me:

#include <iostream> 

using namespace std; 

template <int N> 
int tmax() { 
    return N; 
} 

template <int N, int N1, int... N2> 
int tmax() { 
    return N > tmax<N1, N2...>() ? N : tmax<N1, N2...>(); 
} 

int main() { 
    cout << tmax<32, 43, 54, 12, 23, 34>(); 
} 
+1

Ottimale, grazie. –

+1

La necessità di "dividere" in modo esplicito i parametri pack in modo head/tail mi ha già morso un bel po 'di volte, mi aspetto che ci abitueremo ad esso ... tuttavia non penso che mettere il caso base prima sia obbligatorio , come è, di solito li metto subito dopo. –

0

Dal momento che non si può in parte specializzarsi funzioni, è necessario avvolgere la funzionalità:

template<int Head, int... Tail> 
struct Tmax{ 
    static int do(){ 
    return Head > Tmax<Tail...>::do() ? Head : Tmax<Tail...>::do(); 
    } 
}; 

template<int N> 
struct Tmax<N>{ 
    static int do(){ 
    return N; 
    } 
}; 

template<int... Numbers> 
int tmax(){ 
    return Tmax<Numbers...>::do(); 
} 
+0

non è sicuro se è legale, ma g ++ - 4.5.1 sembra non come la tua risposta: http: // Ideone .com/VXqHv Non ho la mia copia dello standard a portata di mano, quindi non sono sicuro che si tratti di un problema reale o di un vecchio compilatore. – Lambdageek

5

Personalmente, preferisco utilizzare i membri della classe statici sulle funzioni per questo genere di cose:

template <int... N> struct max; 
template <int N, int... M> struct max<N, M...> { 
    static const int value = max<N, max<M...>::value>::value; 
};  
template <int N, int M> struct max<N, M> { 
    static const int value = N > M ? N : M; 
}; 

int main() 
{ 
    return max<1,2,3>::value; 
} 

Aggiornamento: Utilizzando il suggerimento di Ildjarn, ecco la versione meno prolissa:

#include <type_traits> 
template <int... N> struct max; 
template <int N, int... M> struct max<N, M...> 
    : std::integral_constant<int, max<N, max<M...>::value>::value> { }; 
template <int N, int M> struct max<N, M> 
    : std::integral_constant<int, (N > M ? N : M)> { }; 
+0

+1, anche se personalmente deriverei da 'std :: integral_constant' piuttosto che dichiarare' value' manualmente. – ildjarn

+0

@ildjarn: Grazie, aggiornato! Sempre buono per mantenere le cose concise :-) –

+0

che dire: 'modello struct max \t: integral_constant {}; Modello struct max \t: integral_constant max :: valore? a: max :: valore)> {}; ' – sluki

Problemi correlati