4

I found myself writing code like this:

template <class T>
inline bool allequal(T a,T b,T c) {return a==b&&a==c;}
template <class T>
inline bool allequal(T a,T b,T c,T d) {return a==b&&a==c&&a==d;}
template <class T>
inline bool allequal(T a,T b,T c,T d,T e) {return a==b&&a==c&&a==d&&a==e;}

I was wondering if there is an automated way of doing that, without using vectors or variadic arguments, as speed is important in this context.

4
  • 2
    What about variadic templates ? Are you using C++11 ? Commented Jun 5, 2015 at 11:48
  • @Ninetainedo Yes I am using C++11. How would that look like? Can you propose an example? Commented Jun 5, 2015 at 11:51
  • 1
    Why do you think variadic templates slow down code ? Commented Jun 5, 2015 at 11:51
  • 1
    @Jagannath, He is not talking about variadic templates but variadic arguments using va_arg, I guess. Commented Jun 5, 2015 at 11:52

3 Answers 3

4

You could try this:

#include <iostream>

template< typename T >
inline bool allequal( const T& v )
{
  return true;
}

template< typename T, typename U, typename... Ts >
inline bool allequal( const T& v, const U& v1, const Ts&... Vs)
{
  return (v == v1) && allequal( v1, Vs... );
}

int main()
{
    std::cout << std::boolalpha;
    std::cout << allequal(1, 1, 1, 1) << std::endl;
    std::cout << allequal(1, 1, 2, 2) << std::endl;
    return 0;
}

AFAIK there is a proposal for C++17 to include custom expansion of variadic templates with operators that could avoid this kind of recursion and this ugly (IMO) termination with return true for one argument.

Note: this could possibly not be inlined for many arguments.

Sign up to request clarification or add additional context in comments.

4 Comments

Variadic arguments, not templates. He's talking about va_args
This will evaluate to true for (1, 1, 2, 2) and fail to compile for (1, 2, 3). Did you mean allequal(v1, Vs...) (and a recursion stopper with one argument)?
You could combine with all_same to return false; if types are differents.
In C++17 you could use ((v == Vs) && ...) (and omit v1); more details here. clang 3.6 accepts it with std=c++1z; I'm not sure about gcc 5 (4.9 does not).
3
#include <algorithm>
#include <iterator>

template <typename T, typename... Args>
bool allequal(T a, Args... rest)
{
    std::initializer_list<T> values = {a, rest...};
    return std::adjacent_find(begin(values), end(values), std::not_equal_to<T>()) == end(values);
}

Working demo

3 Comments

This is perfect answer. Can you avoid copy by value?
I like the logic behind it. But don't you think that this will be compiled with some sort of for loop, and therefore be less efficient than the other solutions?
I'd have to profile it to see. Both other answers are recursive, this method is iterative. Note that it will short-circuit, so as soon as it finds two elements with not_equal_to, it will bail early without iterating the through the remaining elements. But so will the recursive methods.
2
template<typename First, typename Second>
bool AllOf(First a, Second b)
{
    return a == b;
}

template<typename First, typename Second, typename... Rest>
bool AllOf(First a, Second b, Rest... r)
{
    return  a == b && AllOf(b, r...);
}


std::cout << AllOf(1, 1,1,1) << "\n";
std::cout << AllOf(1, 1,2) << "\n";
std::cout << AllOf(1,2) << "\n";
std::cout << AllOf(1,1) << "\n";

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.