#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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKbmFtZXNwYWNlIG15X21pbiB7CgkKLy8gYSBjb21tb25fdHlwZSB0aGF0IHdoZW4gZmVkIGx2YWx1ZSByZWZlcmVuY2VzIGFsbCBvZiB0aGUgc2FtZSB0eXBlLCByZXR1cm5zIGFuIGx2YWx1ZSByZWZlcmVuY2UgYWxsIG9mIHRoZSBzYW1lIHR5cGUKLy8gaG93ZXZlciwgaXQgaXMgc21hcnQgZW5vdWdoIHRvIGFsc28gdW5kZXJzdGFuZCBjb21tb25fdHlwZSBzcGVjaWFsaXphdGlvbnMuICBUaGlzIHdvcmtzIGFyb3VuZCBhIHF1aXJrCi8vIGluIHRoZSBzdGFuZGFyZCwgd2hlcmUgKHRydWU/eDp5KSBpcyBhbiBsdmFsdWUgcmVmZXJlbmNlLCB3aGlsZSBjb21tb25fdHlwZTwgWCwgWSA+Ojp0eXBlIGlzIG5vdC4KdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHM+CnN0cnVjdCBteV9jb21tb25fdHlwZTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBteV9jb21tb25fdHlwZTxUPnt0eXBlZGVmIFQgdHlwZTt9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVDAsIHR5cGVuYW1lIFQxLCB0eXBlbmFtZS4uLiBUcz4Kc3RydWN0IG15X2NvbW1vbl90eXBlPFQwLCBUMSwgVHMuLi4+IHsKCXR5cGVkZWYgdHlwZW5hbWUgc3RkOjpjb21tb25fdHlwZTxUMCwgVDE+Ojp0eXBlIHN0ZF90eXBlOwoJLy8gaWYgdGhlIHR5cGVzIGFyZSB0aGUgc2FtZSwgZG9uJ3QgY2hhbmdlIHRoZW0sIHVubGlrZSB3aGF0IGNvbW1vbl90eXBlIGRvZXM6Cgl0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6Y29uZGl0aW9uYWw8IHN0ZDo6aXNfc2FtZTwgVDAsIFQxID46OnZhbHVlLAoJCVQwLAoJc3RkX3R5cGUgPjo6dHlwZSB3b3JraW5nX3R5cGU7CgkvLyBDYXJlZnVsISAgV2UgZG8gTk9UIHdhbnQgdG8gcmV0dXJuIGFuIHJ2YWx1ZSByZWZlcmVuY2UuICBKdXN0IHJldHVybiBUOgoJdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OmNvbmRpdGlvbmFsPAoJCXN0ZDo6aXNfcnZhbHVlX3JlZmVyZW5jZTwgd29ya2luZ190eXBlID46OnZhbHVlLAoJCXR5cGVuYW1lIHN0ZDo6ZGVjYXk8IHdvcmtpbmdfdHlwZSA+Ojp0eXBlLAoJCXdvcmtpbmdfdHlwZQoJPjo6dHlwZSBjb21tb25fdHlwZV9mb3JfZmlyc3RfdHdvOwoJLy8gVE9ETzogd2hhdCBhYm91dCBCYXNlJiBhbmQgRGVyaXZlZCY/ICBSZXR1cm5pbmcgYSBCYXNlJiBtaWdodCBiZSB0aGUgcmlnaHQgdGhpbmcgdG8gZG8uCgl0eXBlZGVmIHR5cGVuYW1lIG15X2NvbW1vbl90eXBlPCBjb21tb25fdHlwZV9mb3JfZmlyc3RfdHdvLCBUcy4uLiA+Ojp0eXBlIHR5cGU7Cn07CnRlbXBsYXRlPHR5cGVuYW1lLi4uIFRzPgp1c2luZyBteV9jb21tb25fdHlwZV90ID0gdHlwZW5hbWUgbXlfY29tbW9uX3R5cGU8VHMuLi4+Ojp0eXBlOwoKdGVtcGxhdGU8dHlwZW5hbWUgUGlja2VyLCB0eXBlbmFtZSBUPgpUIHBpY2tlZF9taW4oUGlja2VyJiYgLyp1bnVzZWQqLywgVCYmdCkKewoJcmV0dXJuIHN0ZDo6Zm9yd2FyZDxUPih0KTsKfQovLyBzbGlnaHQgb3B0aW1pemF0aW9uIHdvdWxkIGJlIHRvIG1ha2UgUGlja2VyIGJlIGZvcndhcmQtY2FsbGVkIGF0IHRoZSBhY3R1YWwgMi1hcmcgY2FzZSwgYnV0IEkgZG9uJ3QgY2FyZToKdGVtcGxhdGU8dHlwZW5hbWUgUGlja2VyLCB0eXBlbmFtZSBUMCwgdHlwZW5hbWUgVDEsIHR5cGVuYW1lLi4uIFRzPgpteV9jb21tb25fdHlwZV90PCBUMCwgVDEsIFRzLi4uPiBwaWNrZWRfbWluKFBpY2tlciYmIHBpY2ssIFQwJiYgdmFsMSwgVDEmJiB2YWwyLCBUcyYmLi4uIHZzKQp7CgkvLyBpZiBwaWNrIGRvZXNuJ3QgcHJlZmVyIDIgb3ZlciAxLCB1c2UgMSAtLSBzdGFiaWxpdHkhCglpZiAocGljayh2YWwyLCB2YWwxKSkKCQlyZXR1cm4gcGlja2VkX21pbihzdGQ6OmZvcndhcmQ8UGlja2VyPihwaWNrKSwgdmFsMiwgc3RkOjpmb3J3YXJkPFRzPih2cykuLi4pOwoJZWxzZQoJCXJldHVybiBwaWNrZWRfbWluKHN0ZDo6Zm9yd2FyZDxQaWNrZXI+KHBpY2spLCB2YWwxLCBzdGQ6OmZvcndhcmQ8VHM+KHZzKS4uLik7Cn0KCi8vIHBvc3NpYmx5IHJlcGxhY2Ugd2l0aCBsZXNzPHZvaWQ+IGluIEMrKzF5PwpzdHJ1Y3QgbGVzc2VyIHsKCXRlbXBsYXRlPHR5cGVuYW1lIExIUywgdHlwZW5hbWUgUkhTPgoJYm9vbCBvcGVyYXRvcigpKCBMSFMmJiBsaHMsIFJIUyYmIHJocyApIGNvbnN0IHsKCQlyZXR1cm4gc3RkOjpsZXNzPCB0eXBlbmFtZSBzdGQ6OmRlY2F5PG15X2NvbW1vbl90eXBlX3Q8TEhTLCBSSFM+Pjo6dHlwZSA+KCkoCgkJCQlzdGQ6OmZvcndhcmQ8TEhTPihsaHMpLCBzdGQ6OmZvcndhcmQ8UkhTPihyaHMpCgkJKTsKCX0KfTsKLy8gc2ltcGx5IGZvcndhcmQgdG8gdGhlIHBpY2tlZF9taW4gZnVuY3Rpb24gd2l0aCBhIHNtYXJ0IGxlc3MgdGhhbiBmdW5jdG9yCi8vIG5vdGUgdGhhdCB3ZSBzdXBwb3J0IHVucmVsYXRlZCBwb2ludGVycyEKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHM+CmF1dG8gbWluKCBUcyYmLi4uIHRzICktPmRlY2x0eXBlKCBwaWNrZWRfbWluKCBsZXNzZXIoKSwgc3RkOjpkZWNsdmFsPFRzPigpLi4uICkgKQp7CglyZXR1cm4gcGlja2VkX21pbiggbGVzc2VyKCksIHN0ZDo6Zm9yd2FyZDxUcz4odHMpLi4uICk7Cn0KfQppbnQgbWFpbigpCnsKCWludCB4ID0gNzsKCWludCB5ID0gMzsKCWludCB6ID0gLTE7CiAJbXlfbWluOjptaW4oeCwgeSwgeikgPSAyOwoJc3RkOjpjb3V0IDw8IHggPDwgIiwiIDw8IHkgPDwgIiwiIDw8IHogPDwgIlxuIjsKCXN0ZDo6Y291dCA8PCBteV9taW46Om1pbigzLCAyLCAwLjksIDIsIDUpIDw8IHN0ZDo6ZW5kbDsKCXN0ZDo6Y291dCA8PCBteV9taW46Om1pbigzLiwgMS4yLCAxLjMsIDIuLCA1LjIpIDw8IHN0ZDo6ZW5kbDsKCXJldHVybiAwOwp9Cg==