2015-02-04 14 views
8

Qual è la differenza tra i seguenti 2 pezzi di codice:argomenti Template vs argomenti della funzione

1:

template<size_t min, size_t max> 
bool byLength(const std::string& v) 
{ 
    return v.length() >= min && v.length() <= max; 
} 

2:

bool byLength(const std::string& v, size_t min, size_t max) 
{ 
    return v.length() >= min && v.length() <= max; 
} 

Qual è caso d'uso principale di utilizzare argomenti di template invece di argomenti di funzione? Perché non usare solo il secondo esempio?

+7

I modelli sono risolti a * tempo di compilazione *, gli argomenti vengono valutati in * tempo di esecuzione *. Ciò significa che gli argomenti del template devono essere costanti per poter essere risolti dal compilatore, mentre gli argomenti della funzione possono essere cose come input di utilizzo che è impossibile valutare al momento della compilazione. –

+0

Ok, sembra che capisco la stupidità della domanda. Posso eliminarlo? –

+1

Si chiamano differentemente: 'byLength (string)' vs 'byLength (string, min, max)'. Se questo fa la differenza per i tuoi occhi. – rubikonx9

risposta

9

Qual è la differenza tra i seguenti 2 pezzi di codice?

Gli argomenti del modello devono essere costanti, specificati al momento della compilazione. Gli argomenti della funzione sono variabili e non devono essere conosciuti al momento della compilazione.

Per illustrare, con il modello:

byLength<5,10>(v);  // OK 

size_t min,max; 
std::cin >> min >> max; 
byLength<min,max>(v); // ERROR: must be constants 

mentre con argomenti delle funzioni:

byLength(v, 5, 10);  // OK 

size_t min,max; 
std::cin >> min >> max; 
byLength(v, min, max); // OK 

Qual è caso d'uso principale di utilizzare argomenti di template invece di argomenti della funzione?

Essendo costanti, possono offrire un'ottimizzazione migliore e possono essere utilizzate in situazioni (come le dimensioni di un array) dove sono consentite solo le costanti.

Perché non usare solo il secondo esempio?

In questo caso, perché no? Ciò sarebbe più flessibile, in quanto è possibile calcolare gli argomenti in fase di esecuzione o recuperarli dall'input del programma. Se è in linea, dovrebbe essere efficiente quanto il modello quando viene chiamato con valori costanti.

2

La differenza più grande è quello che si può fare con queste due funzioni:

  • La funzione template prende i suoi due limiti come parametri del modello, il che significa che devono essere noti al momento della compilazione
  • Il la funzione regolare prende i suoi due limiti come parametri regolari, il che significa che puoi usare variabili per loro.

In sostanza, la seconda funzione permette di fare questo

int a, b; 
cout << "Please enter two limits: "; 
cin >> a >> b; 
string s("quick brown fox"); 
bool res = byLength(s, a, b); 

Questo non è possibile con la funzione di modello:

int a, b; 
cout << "Please enter two limits: "; 
cin >> a >> b; 
string s("quick brown fox"); 
bool res = byLength<a,b>(s); // <<== DOES NOT COMPILE. 

Se tutte le chiamate utilizzano espressioni costanti per i parametri limite, la funzione template può farti risparmiare un paio di cicli extra della CPU, perché il compilatore può ottimizzare meglio la sua ottimizzazione. È difficile immaginare una situazione in cui questi cicli aggiuntivi farebbero una differenza significativa.

Perché non usare solo il secondo esempio?

Ci sono situazioni in cui hai bisogno di una costante in fase di compilazione nella tua funzione. Ad esempio, se si desidera dichiarare un std::array<len> sulla base di uno dei parametri, deve essere passato come parametro di template, non come un parametro regolare:

template<size_t sz> 
void demo() { 
    std::array<sz> data; 
    ... 
} 

Lo stesso non avrebbe funzionato con parametri di funzionamento regolari:

void demo(size_t sz) { 
    std::array<sz> data; // <<== DOES NOT COMPILE. 
    ... 
} 
1

Non è possibile chiamare il modello con valori che non sono consexpr.

L'esempio più semplice sarebbe qualcosa di simile a questo:

1 può essere chiamato con questo codice:

const auto Min = numeric_limits<int>::min(); 
const auto Max = numeric_limits<int>::max(); 

byLength<Min, Max>(string()); 

si dovrebbe utilizzare 2 per valori noti solo in fase di esecuzione:

cin >> Min >> Max; 

// Cannot call by byLength<Min, Max>(string()); because the values are not constexpr 
byLength(string(), Min, Max); 
Problemi correlati