#include <tuple>
#include <cstring>
#include <functional>
#include <type_traits>
size_t hash_combiner(size_t left, size_t right) //replacable
{ return left^right;}
template<int index, class...types>
struct hash_impl {
size_t operator()(size_t a, const std::tuple<types...>& t) const {
typedef typename std::tuple_element<index, std::tuple<types...>>::type nexttype;
hash_impl<index-1, types...> next;
size_t b = std::hash<nexttype>()(std::get<index>(t));
return next(hash_combiner(a, b), t);
}
};
template<class...types>
struct hash_impl<0, types...> {
size_t operator()(size_t a, const std::tuple<types...>& t) const {
typedef typename std::tuple_element<0, std::tuple<types...>>::type nexttype;
size_t b = std::hash<nexttype>()(std::get<0>(t));
return hash_combiner(a, b);
}
};
namespace std {
template<class...types>
struct hash<std::tuple<types...>> {
size_t operator()(const std::tuple<types...>& t) {
const size_t begin = std::tuple_size<std::tuple<types...>>::value-1;
return hash_impl<begin, types...>()(1, t); //1 should be some largervalue
}
};
}
#include <iostream>
int main() {
typedef std::tuple<int, char, float> T;
T t(14, 'A', 3.14);
std::cout << std::hash<T>()(t);
return 0;
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8Y3N0cmluZz4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KIApzaXplX3QgaGFzaF9jb21iaW5lcihzaXplX3QgbGVmdCwgc2l6ZV90IHJpZ2h0KSAvL3JlcGxhY2FibGUKeyByZXR1cm4gbGVmdF5yaWdodDt9CiAKdGVtcGxhdGU8aW50IGluZGV4LCBjbGFzcy4uLnR5cGVzPgpzdHJ1Y3QgaGFzaF9pbXBsIHsKICAgIHNpemVfdCBvcGVyYXRvcigpKHNpemVfdCBhLCBjb25zdCBzdGQ6OnR1cGxlPHR5cGVzLi4uPiYgdCkgY29uc3QgewogICAgICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PGluZGV4LCBzdGQ6OnR1cGxlPHR5cGVzLi4uPj46OnR5cGUgbmV4dHR5cGU7CiAgICAgICAgaGFzaF9pbXBsPGluZGV4LTEsIHR5cGVzLi4uPiBuZXh0OwogICAgICAgIHNpemVfdCBiID0gc3RkOjpoYXNoPG5leHR0eXBlPigpKHN0ZDo6Z2V0PGluZGV4Pih0KSk7CiAgICAgICAgcmV0dXJuIG5leHQoaGFzaF9jb21iaW5lcihhLCBiKSwgdCk7IAogICAgfQp9Owp0ZW1wbGF0ZTxjbGFzcy4uLnR5cGVzPgpzdHJ1Y3QgaGFzaF9pbXBsPDAsIHR5cGVzLi4uPiB7CiAgICBzaXplX3Qgb3BlcmF0b3IoKShzaXplX3QgYSwgY29uc3Qgc3RkOjp0dXBsZTx0eXBlcy4uLj4mIHQpIGNvbnN0IHsKICAgICAgICB0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6dHVwbGVfZWxlbWVudDwwLCBzdGQ6OnR1cGxlPHR5cGVzLi4uPj46OnR5cGUgbmV4dHR5cGU7CiAgICAgICAgc2l6ZV90IGIgPSBzdGQ6Omhhc2g8bmV4dHR5cGU+KCkoc3RkOjpnZXQ8MD4odCkpOwogICAgICAgIHJldHVybiBoYXNoX2NvbWJpbmVyKGEsIGIpOyAKICAgIH0KfTsKCm5hbWVzcGFjZSBzdGQgewogICAgdGVtcGxhdGU8Y2xhc3MuLi50eXBlcz4KICAgIHN0cnVjdCBoYXNoPHN0ZDo6dHVwbGU8dHlwZXMuLi4+PiB7CiAgICAgICAgc2l6ZV90IG9wZXJhdG9yKCkoY29uc3Qgc3RkOjp0dXBsZTx0eXBlcy4uLj4mIHQpIHsKICAgICAgICAgICAgY29uc3Qgc2l6ZV90IGJlZ2luID0gc3RkOjp0dXBsZV9zaXplPHN0ZDo6dHVwbGU8dHlwZXMuLi4+Pjo6dmFsdWUtMTsKICAgICAgICAgICAgcmV0dXJuIGhhc2hfaW1wbDxiZWdpbiwgdHlwZXMuLi4+KCkoMSwgdCk7IC8vMSBzaG91bGQgYmUgc29tZSBsYXJnZXJ2YWx1ZQogICAgICAgIH0KICAgIH07Cn0KCiNpbmNsdWRlIDxpb3N0cmVhbT4KIAppbnQgbWFpbigpIHsKICAgIHR5cGVkZWYgc3RkOjp0dXBsZTxpbnQsIGNoYXIsIGZsb2F0PiBUOwogICAgVCB0KDE0LCAnQScsIDMuMTQpOwogICAgc3RkOjpjb3V0IDw8IHN0ZDo6aGFzaDxUPigpKHQpOwogICAgcmV0dXJuIDA7Cn0=