I would suggest yao99's answer should be the accepted one. For sake of curiosity, here I present you with a solution that provides an adaptor through your own namespace. This only ever uses the binary parameter overload of std::max
so there is no possibility of the initialiser list overload becoming invoked. The client code can still use max
as indicated:
The adaptor:
#include <iostream>
#include <algorithm>
namespace variadicMax
{
// the variadic "max" recurses and reduces to a binary parameter version that we must implement
template<typename T>
constexpr inline T const& max(T const&x, T const&y)
{
return (std::max(x, y));
}
// the variadic overload recurses itself, removing two parameters (and adding one) each time.
// Eventually it reduces to (x,y) which is handled by the other overload.
template<typename T, typename...Args>
constexpr inline T const& max(T const&x, T const&y, Args&&...z)
{
return (max (std::max(x, y), std::forward<Args>(z)...));
}
};
The client:
// this is the only change needed in clients:
using variadicMax::max;
int main()
{
double x, y, z, w, v;
x = 1; y = 2; z = 3; w = 4; v = 5;
auto m5 = max(x, y, z, w, v); std::cout << m5 << std::endl;
auto m5A = max(x, y, z, 4.0, v); std::cout << m5A << std::endl;
x = 1; y = 2; z = 3;
auto m = max(x, y, z); std::cout << m << std::endl;
x = 2; y = 3; z = 1;
auto m2 = max(x, y, z); std::cout << m2 << std::endl;
x = 3; y = 2; z = 1;
auto m3 = max(x, y, z); std::cout << m3 << std::endl;
x = 3; y = 2;
auto m4 = max(x, y); std::cout << m4 << std::endl;
x = 3; y = 2;
auto m6 = max(3, 2); std::cout << m6 << std::endl;
x = 3; y = 2;
auto m7 = max(x, 2.0); std::cout << m7 << std::endl;
etc...