#include <iostream>
#include <utility>
#include <type_traits>

namespace my_min {
	
// a common_type that when fed lvalue references all of the same type, returns an lvalue reference all of the same type
// however, it is smart enough to also understand common_type specializations.  This works around a quirk
// in the standard, where (true?x:y) is an lvalue reference, while common_type< X, Y >::type is not.
template<typename... Ts>
struct my_common_type;

template<typename T>
struct my_common_type<T>{typedef T type;};

template<typename T0, typename T1, typename... Ts>
struct my_common_type<T0, T1, Ts...> {
	typedef typename std::common_type<T0, T1>::type std_type;
	// if the types are the same, don't change them, unlike what common_type does:
	typedef typename std::conditional< std::is_same< T0, T1 >::value,
		T0,
	std_type >::type working_type;
	// Careful!  We do NOT want to return an rvalue reference.  Just return T:
	typedef typename std::conditional<
		std::is_rvalue_reference< working_type >::value,
		typename std::decay< working_type >::type,
		working_type
	>::type common_type_for_first_two;
	// TODO: what about Base& and Derived&?  Returning a Base& might be the right thing to do.
	typedef typename my_common_type< common_type_for_first_two, Ts... >::type type;
};
template<typename... Ts>
using my_common_type_t = typename my_common_type<Ts...>::type;

template<typename Picker, typename T>
T picked_min(Picker&& /*unused*/, T&&t)
{
	return std::forward<T>(t);
}
// slight optimization would be to make Picker be forward-called at the actual 2-arg case, but I don't care:
template<typename Picker, typename T0, typename T1, typename... Ts>
my_common_type_t< T0, T1, Ts...> picked_min(Picker&& pick, T0&& val1, T1&& val2, Ts&&... vs)
{
	// if pick doesn't prefer 2 over 1, use 1 -- stability!
	if (pick(val2, val1))
		return picked_min(std::forward<Picker>(pick), val2, std::forward<Ts>(vs)...);
	else
		return picked_min(std::forward<Picker>(pick), val1, std::forward<Ts>(vs)...);
}

// possibly replace with less<void> in C++1y?
struct lesser {
	template<typename LHS, typename RHS>
	bool operator()( LHS&& lhs, RHS&& rhs ) const {
		return std::less< typename std::decay<my_common_type_t<LHS, RHS>>::type >()(
				std::forward<LHS>(lhs), std::forward<RHS>(rhs)
		);
	}
};
// simply forward to the picked_min function with a smart less than functor
// note that we support unrelated pointers!
template<typename... Ts>
auto min( Ts&&... ts )->decltype( picked_min( lesser(), std::declval<Ts>()... ) )
{
	return picked_min( lesser(), std::forward<Ts>(ts)... );
}
}
int main()
{
	int x = 7;
	int y = 3;
	int z = -1;
 	my_min::min(x, y, z) = 2;
	std::cout << x << "," << y << "," << z << "\n";
	std::cout << my_min::min(3, 2, 0.9, 2, 5) << std::endl;
	std::cout << my_min::min(3., 1.2, 1.3, 2., 5.2) << std::endl;
	return 0;
}
