2016-03-15 16 views
7

Ho il seguente esempio in cui vengono utilizzati due parametri t1 e t2.Funzione modello variabile con più di due parametri

template<typename T> 
bool Compare(T t1, T t2) 
{ 
    return t1 == t2; 
} 

template<typename T, typename... Args> 
bool Compare(T t1, T t2, Args... args) 
{ 
    return (t1 == t2) && Compare(args...); 
} 

int main(void) 
{ 
    Compare(1, 1, "string", "string"); 
} 

Funzione Confronta prende coppie di parametri che sono dello stesso tipo e possono essere confrontati. Due coppie vengono confrontate, quindi il pacchetto di parametri viene passato in modo ricorsivo fino a quando non vengono raggiunti gli ultimi due parametri. Per interrompere la ricorsione, utilizzo un'implementazione della funzione Confronta senza il pacchetto di parametri.

vorrei aggiungere il terzo t3 argomento così funzione Confronta dovrebbe essere simile a questo:

template<typename T> 
bool Compare(T t1, T t2, T t3) 
{ 
    return t1 == t2 == t3; 
} 

template<typename T, typename... Args> 
bool Compare(T t1, T t2, T t3, Args... args) 
{ 
    return (t1 == t2 == t3) && Compare(args...); 
} 

int main(void) 
{ 
    Compare(1, 1, 1, "string", "string", "string"); 
} 

mi aspetto che questa funzione prende tre parametri di confronto, allora il prossimo tre sono trattati in modo ricorsivo. Quando provo a compilare questo codice ottengo il seguente errore:

>xxx\source.cpp(4): error C2446: '==': no conversion from 'const char *' to 'int' 
1> xxx\source.cpp(4): note: There is no context in which this conversion is possible 
1> xxx\source.cpp(10): note: see reference to function template instantiation 'bool Compare<const char*>(T,T,T)' being compiled 
1>   with 
1>   [ 
1>    T=const char * 
1>   ] 
1> xxx\source.cpp(15): note: see reference to function template instantiation 'bool Compare<int,const char*,const char*,const char*>(T,T,T,const char *,const char *,const char *)' being compiled 
1>   with 
1>   [ 
1>    T=int 
1>   ] 
1>xxx\source.cpp(4): error C2040: '==': 'int' differs in levels of indirection from 'const char *' 

Come implementare questa funzione per confrontare i gruppi di tre parametri dello stesso tipo?

risposta

8
t1 == t2 == t3 

che non verifica se t1, t2 e t3 sono tutti uguali, controlla se t1 uguale t2, quindi controlla se il risultato è uguale a boolt3.

Forse ciò che si vuole invece è (supponendo operatori di uguaglianza ragionevoli):

t1 == t2 && t1 == t3 

Quindi il codice sarebbe simile a questa:

template<typename T> 
bool Compare(T t1, T t2, T t3) 
{ 
    return t1 == t2 && t1 == t3; 
} 

template<typename T, typename... Args> 
bool Compare(T t1, T t2, T t3, Args... args) 
{ 
    return t1 == t2 && t1 == t3 && Compare(args...); 
} 

Nota che la chiamata di prova con le stringhe fa confronto puntatore , che potrebbe non essere quello che vuoi.

+0

Per espandere sull'ultima riga: passando il c_str() di una stringa std contenente "stringa" come uno degli argomenti valuterebbe falsa, anche se tutte le stringhe dicono "stringa" - hanno posizioni diverse in memoria . Dovresti preferire l'utilizzo delle stringhe std (che include il wrapping di costanti stringa in esse) ogni volta che è possibile. –

0

Ecco la mia soluzione più generale. compareConsecutive<N> restituirà true solo se N argomenti consecutivi sono tutti uguali per tutti i blocchi di argomenti N.

#include <iostream> 
#include <tuple> 
#include <utility> 

template <std::size_t Start, typename IndexSequence> struct MakeIndexSequenceHelper; 

template <std::size_t Start, std::size_t... Is> 
struct MakeIndexSequenceHelper<Start, std::index_sequence<Is...>> { 
    using type = std::index_sequence<(Start + Is)...>; 
}; 

template <std::size_t Start, std::size_t Length> 
struct MakeIndexSequence : MakeIndexSequenceHelper<Start, std::make_index_sequence<Length>> {}; 

template <typename T, typename U> 
bool allAreSame (const T&, const U&) { 
    return false; 
} 

template <typename T> 
bool allAreSame (const T& t1, const T& t2) { 
    return t1 == t2; 
} 

template <typename T, typename U, typename... Args> 
bool allAreSame (const T&, const U&, const Args&...) { 
    return false; 
} 

template <typename T, typename... Args> 
bool allAreSame (const T& t1, const T& t2, const Args&... args) { 
    return allAreSame(t1, t2) && allAreSame(t1, args...); 
} 

template <typename Tuple, std::size_t... Is> 
bool allAreSameHelper (Tuple&& tuple, std::index_sequence<Is...>) { 
    return allAreSame (std::get<Is>(std::forward<Tuple>(tuple))...); 
} 

template <std::size_t N, typename... Args> 
bool allAreSameHelper (Args&&... args) { 
    return allAreSameHelper (std::forward_as_tuple(std::forward<Args>(args)...), std::make_index_sequence<N>{}); 
} 

template <std::size_t N, typename... Args> bool compareConsecutive (Args&&...); 

template <std::size_t N> 
bool compareConsecutive() {return true;} 

template <std::size_t N, typename Tuple, std::size_t... Is> 
bool compareConsecutiveHelper (Tuple&& tuple, std::index_sequence<Is...>) { 
    return compareConsecutive<N> (std::get<Is>(std::forward<Tuple>(tuple))...); 
} 

template <std::size_t N, std::size_t Start, std::size_t Length, typename... Args> 
bool compareConsecutiveHelper (Args&&... args) { 
    return compareConsecutiveHelper<N> (std::forward_as_tuple(std::forward<Args>(args)...), typename MakeIndexSequence<Start, Length>::type{}); 
} 

template <std::size_t N, typename... Args> 
bool compareConsecutive (Args&&... args) { 
    return allAreSameHelper<N>(std::forward<Args>(args)...) && compareConsecutiveHelper<N, N, sizeof...(Args) - N>(args...); 
} 

int main() { 
    std::cout << std::boolalpha << allAreSame("hi", "hi", "hi", "hi", "hi", "hi") << '\n'; // true 
    std::cout << compareConsecutive<2>(1, 1, "hi", "hi") << '\n'; // true 
    std::cout << compareConsecutive<2>(1, "hi", "hi", "hi") << '\n'; // false 
    std::cout << compareConsecutive<3>(1, 1, 1, "hi", "hi", "hi", 4.5, 4.5, 4.5) << '\n'; // true 
    std::cout << compareConsecutive<5>(1, 1, 1, 1, 1, "hi", "hi", "hi", "hi", "hi") << '\n'; // true 
    std::cout << compareConsecutive<5>(1, 1, 1, 1, 2, "hi", "hi", "hi", "hi", "hi") << '\n'; // false 
} 
Problemi correlati