#include <annex/meta.hpp>
#include <annex/indices.hpp>
using annex::Int;
using annex::indices;
using annex::Indices;
using annex::meta::list;
using annex::Void;
template<typename C, int I>
struct candidate {
static Int<I> test(C);
};
template<typename T, typename Candidates, typename Indices>
struct best_match_impl {
static Int<-1> test(...);
};
template<typename T, typename C, typename... Cs, int I, int... Is>
struct best_match_impl<T, list<C, Cs...>, indices<I, Is...>>
: candidate<C, I>, best_match_impl<T, list<Cs...>, indices<Is...>> {
using candidate<C, I>::test;
using best_match_impl<T, list<Cs...>, indices<Is...>>::test;
};
template<typename T, typename Candidates, typename Indices = Indices<Candidates::size::value>, typename Sfinae = void>
struct best_match: Int<-2> {};
template<typename T, typename Candidates, typename Indices>
struct best_match<
T, Candidates, Indices
, Void<decltype(best_match_impl<T, Candidates, Indices>::test(std::declval<T>()))>
>
: decltype(best_match_impl<T, Candidates, Indices>::test(std::declval<T>())) {};
I2luY2x1ZGUgPGFubmV4L21ldGEuaHBwPgojaW5jbHVkZSA8YW5uZXgvaW5kaWNlcy5ocHA+Cgp1c2luZyBhbm5leDo6SW50Owp1c2luZyBhbm5leDo6aW5kaWNlczsKdXNpbmcgYW5uZXg6OkluZGljZXM7CnVzaW5nIGFubmV4OjptZXRhOjpsaXN0Owp1c2luZyBhbm5leDo6Vm9pZDsKCnRlbXBsYXRlPHR5cGVuYW1lIEMsIGludCBJPgpzdHJ1Y3QgY2FuZGlkYXRlIHsKICAgIHN0YXRpYyBJbnQ8ST4gdGVzdChDKTsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIENhbmRpZGF0ZXMsIHR5cGVuYW1lIEluZGljZXM+CnN0cnVjdCBiZXN0X21hdGNoX2ltcGwgewogICAgc3RhdGljIEludDwtMT4gdGVzdCguLi4pOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgQywgdHlwZW5hbWUuLi4gQ3MsIGludCBJLCBpbnQuLi4gSXM+CnN0cnVjdCBiZXN0X21hdGNoX2ltcGw8VCwgbGlzdDxDLCBDcy4uLj4sIGluZGljZXM8SSwgSXMuLi4+Pgo6IGNhbmRpZGF0ZTxDLCBJPiwgYmVzdF9tYXRjaF9pbXBsPFQsIGxpc3Q8Q3MuLi4+LCBpbmRpY2VzPElzLi4uPj4gewogICAgdXNpbmcgY2FuZGlkYXRlPEMsIEk+Ojp0ZXN0OwogICAgdXNpbmcgYmVzdF9tYXRjaF9pbXBsPFQsIGxpc3Q8Q3MuLi4+LCBpbmRpY2VzPElzLi4uPj46OnRlc3Q7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBDYW5kaWRhdGVzLCB0eXBlbmFtZSBJbmRpY2VzID0gSW5kaWNlczxDYW5kaWRhdGVzOjpzaXplOjp2YWx1ZT4sIHR5cGVuYW1lIFNmaW5hZSA9IHZvaWQ+CnN0cnVjdCBiZXN0X21hdGNoOiBJbnQ8LTI+IHt9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgQ2FuZGlkYXRlcywgdHlwZW5hbWUgSW5kaWNlcz4Kc3RydWN0IGJlc3RfbWF0Y2g8CiAgICBULCBDYW5kaWRhdGVzLCBJbmRpY2VzCiAgICAsIFZvaWQ8ZGVjbHR5cGUoYmVzdF9tYXRjaF9pbXBsPFQsIENhbmRpZGF0ZXMsIEluZGljZXM+Ojp0ZXN0KHN0ZDo6ZGVjbHZhbDxUPigpKSk+Cj4KOiBkZWNsdHlwZShiZXN0X21hdGNoX2ltcGw8VCwgQ2FuZGlkYXRlcywgSW5kaWNlcz46OnRlc3Qoc3RkOjpkZWNsdmFsPFQ+KCkpKSB7fTs=