A piece of code is worth a thousand words:
int main()
{
// All of the following calls return true:
AreEqual(1, 1);
AreEqual(1, 1, 1);
AreEqual(1, 1, 1, 1);
AreEqual(1, 1, 1, 1, 1);
// All of the following calls return false:
AreEqual(1, 2);
AreEqual(1, 2, 1);
AreEqual(1, 7, 3, 1);
AreEqual(1, 4, 1, 1, 1);
}
How to implement the function AreEqual() that accepts arbitrary number of arguments?
The trivial but tedious soultion is through overloading:
bool AreEqual(int v1, int v2);
bool AreEqual(int v1, int v2, int v3);
bool AreEqual(int v1, int v2, int v3, int v4);
......
Another trivial but not workable solution is:
bool AreEqual(...);
This solution is not workable, because the caller must add another argument (argument count or ending marker) to specify the number of the arguments.
Yet another way is through variadic template arguments
template<class... Args>
bool AreEqual(Args... args)
{
// What should be placed here ???
}
Here is how one can implement it with templates:
#include <iostream>
#include <iomanip>
template<class T0>
bool AreEqual(T0 t0) { return true; }
template<class T0, class T1, class... Args>
bool AreEqual(T0 t0, T1 t1, Args ... args) {
return t0 == t1 && AreEqual(t1, args...);
}
int main () {
std::cout << std::boolalpha;
// All of the following calls return true:
std::cout<< AreEqual(1, 1) << "\n";
std::cout<< AreEqual(1, 1, 1) << "\n";
std::cout<< AreEqual(1, 1, 1, 1) << "\n";
std::cout<< AreEqual(1, 1, 1, 1, 1) << "\n\n";
// All of the following calls return false:
std::cout<< AreEqual(1, 2) << "\n";
std::cout<< AreEqual(1, 2, 1) << "\n";
std::cout<< AreEqual(1, 7, 3, 1) << "\n";
std::cout<< AreEqual(1, 4, 1, 1, 1) << "\n";
}
You should consider whether these variations are appropriate for your use:
template<typename T, typename... Args>
bool AreEqual(T first, Args... args)
{
return std::min({first==args...});
}
template<typename T, typename... Args>
bool AreEqual(T first, Args... args)
{
for(auto i : {args...})
if(first != i)
return false;
return true;
}
Since you seem to be ruling out the sensible way to do it for some reason you could also try using std::initializer_list
:
template<typename T>
bool AreEqual(std::initializer_list<T> list) {
...
}
Then you'd call it like:
AreEqual({1,1,1,1,1});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With