#include <tuple>
#include <unordered_map>
#include <cassert>
#include <iostream>
struct triplet
{
unsigned a,b,c;
bool operator< (triplet const& o) const { return std::tie(a,b,c) < std::tie(o.a,o.b,o.c); }
bool operator==(triplet const& o) const { return std::tie(a,b,c) ==std::tie(o.a,o.b,o.c); }
};
namespace std {
template<> struct hash<triplet> {
unsigned int operator()(triplet const& key) const {
return ~key.a + 17u*key.b + 17u*key.c; // totally made that up, could be better, I suppose
}
};
}
static std::ostream& operator<<(std::ostream& os, triplet const& key) {
return os << '[' << key.a << ',' << key.b << ',' << key.c << ']';
}
int main()
{
std::unordered_multimap<triplet, double> map;
// insert items dynamically
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 3 }, 0.1 } );
map.insert({ triplet{ /*I*/ 4, /*J*/ 5, /*K*/ 6 }, 0.2 } );
map.insert({ triplet{ /*I*/ 7, /*J*/ 8, /*K*/ 9 }, 0.3 } );
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 0 }, 0.4 } ); // duplicate (I,J) ok
map.insert({ triplet{ /*I*/ 1, /*J*/ 2, /*K*/ 0 }, 0.5 } );
assert(0 == map.count(triplet {1,5,6}));
assert(1 == map.count(triplet {4,5,6}));
auto range = map.equal_range(triplet { 1,2,0 });
for (auto it=range.first; it!=range.second; ++it)
std::cout << it->first << ": " << it->second << "\n";
}
I2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4KI2luY2x1ZGUgPGNhc3NlcnQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnN0cnVjdCB0cmlwbGV0IAp7IAoJdW5zaWduZWQgYSxiLGM7Cglib29sIG9wZXJhdG9yPCAodHJpcGxldCBjb25zdCYgbykgY29uc3QgeyByZXR1cm4gc3RkOjp0aWUoYSxiLGMpIDwgc3RkOjp0aWUoby5hLG8uYixvLmMpOyB9Cglib29sIG9wZXJhdG9yPT0odHJpcGxldCBjb25zdCYgbykgY29uc3QgeyByZXR1cm4gc3RkOjp0aWUoYSxiLGMpID09c3RkOjp0aWUoby5hLG8uYixvLmMpOyB9Cn07CgpuYW1lc3BhY2Ugc3RkIHsKICAgIHRlbXBsYXRlPD4gc3RydWN0IGhhc2g8dHJpcGxldD4gewogICAgICAgIHVuc2lnbmVkIGludCBvcGVyYXRvcigpKHRyaXBsZXQgY29uc3QmIGtleSkgY29uc3QgeyAKICAgICAgICAgICAgcmV0dXJuICB+a2V5LmEgKyAxN3Uqa2V5LmIgKyAxN3Uqa2V5LmM7IC8vIHRvdGFsbHkgbWFkZSB0aGF0IHVwLCBjb3VsZCBiZSBiZXR0ZXIsIEkgc3VwcG9zZQogICAgICAgIH0KICAgIH07Cn0KCnN0YXRpYyBzdGQ6Om9zdHJlYW0mIG9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtJiBvcywgdHJpcGxldCBjb25zdCYga2V5KSB7CiAgICByZXR1cm4gb3MgPDwgJ1snIDw8IGtleS5hIDw8ICcsJyA8PCBrZXkuYiA8PCAnLCcgPDwga2V5LmMgPDwgJ10nOwp9CgppbnQgbWFpbigpCnsKICAgIHN0ZDo6dW5vcmRlcmVkX211bHRpbWFwPHRyaXBsZXQsIGRvdWJsZT4gbWFwOwogICAgCiAgICAvLyBpbnNlcnQgaXRlbXMgZHluYW1pY2FsbHkKICAgIG1hcC5pbnNlcnQoeyB0cmlwbGV0eyAvKkkqLyAxLCAvKkoqLyAyLCAvKksqLyAzIH0sICAwLjEgfSApOwogICAgbWFwLmluc2VydCh7IHRyaXBsZXR7IC8qSSovIDQsIC8qSiovIDUsIC8qSyovIDYgfSwgIDAuMiB9ICk7CiAgICBtYXAuaW5zZXJ0KHsgdHJpcGxldHsgLypJKi8gNywgLypKKi8gOCwgLypLKi8gOSB9LCAgMC4zIH0gKTsKICAgIG1hcC5pbnNlcnQoeyB0cmlwbGV0eyAvKkkqLyAxLCAvKkoqLyAyLCAvKksqLyAwIH0sICAwLjQgfSApOyAvLyBkdXBsaWNhdGUgKEksSikgb2sKCiAgICBtYXAuaW5zZXJ0KHsgdHJpcGxldHsgLypJKi8gMSwgLypKKi8gMiwgLypLKi8gMCB9LCAwLjUgfSApOwoKICAgIGFzc2VydCgwID09IG1hcC5jb3VudCh0cmlwbGV0IHsxLDUsNn0pKTsKICAgIGFzc2VydCgxID09IG1hcC5jb3VudCh0cmlwbGV0IHs0LDUsNn0pKTsKCiAgICBhdXRvIHJhbmdlID0gbWFwLmVxdWFsX3JhbmdlKHRyaXBsZXQgeyAxLDIsMCB9KTsKICAgIGZvciAoYXV0byBpdD1yYW5nZS5maXJzdDsgaXQhPXJhbmdlLnNlY29uZDsgKytpdCkKICAgICAgICBzdGQ6OmNvdXQgPDwgaXQtPmZpcnN0IDw8ICI6ICIgPDwgaXQtPnNlY29uZCA8PCAiXG4iOwp9Cg==