Variadic template function with more than two parameters

I have the following example where two parameters t1 and t2 are used.

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

The Compare function accepts pairs of parameters of the same type and can be compared. Two pairs are compared, then the parameter packet is passed recursively until the last two parameters are reached. To stop recursion, I use an implementation of a comparison function without a parameter package.

I would like to add the third argument to t3, so the Compare function should look something like this:

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

I expect this function to take three parameters for comparison, then the next three are processed recursively. When I try to compile this code, I get the following error:

 >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 *' 

How to implement this function to compare sets of three parameters of the same type?

+7
c ++ recursion variadic-templates
source share
2 answers
 t1 == t2 == t3 

This does not check if all t1 , t2 and t3 are equal, it checks if t1 is equal to t2 , then the resulting bool is equal to t3 .

Perhaps you want instead (assuming reasonable equality operators):

 t1 == t2 && t1 == t3 

So your code will look like this:

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

Note that your test call with string literals does a pointer comparison, which may not be what you want.

+8
source share

Here is my more general solution. compareConsecutive<N> will return true only if N consecutive arguments are equal for all blocks of N arguments.

 #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 } 
0
source share

All Articles