Home > Net >  How could I use unordered_set with triplets being its elements?
How could I use unordered_set with triplets being its elements?

Time:09-07

I want to use triplets to be elements of unordered_set . I want to check whether a combination of three values has been present or not:

unordered_set<long, long, long> myset;
myset.insert(0, 1, 0);

Obviously that's not correct. How could I do this correctly? Thank you for your help.

-------Updated-------

If I don't use unordered_set, is there any other easier way to check whether a combination has been present or not? Thank you for your help.

CodePudding user response:

From the std, you probably want to use std::unordered_set<std::tuple<long, long, long>, Hasher> or std::unordered_set<std::array<long, 3>, Hasher>.

That said, as suggested by @Evg, a struct would hold more meaning.

If you look at std::unordered_set's documentation you can see that it takes the element only as the first template parameter, the others are used for other types.


Unfortunately as @Evg pointed out, these types need a custom hasher. Here is a hasher's basic structure:

struct Hasher {
                        // v Here goes your set's type
    std::size_t operator()(std::tuple<long, long, long> const& key) const {                                              
        return /* the hash */;                                 
    }                                              
};

You can find an implementation example at cppreference's hash page.

CodePudding user response:

First you should define hash function for such an element. I'm not a big expert in hashing, but standard approach would look something like this:

using el_type = std::tuple<long, long, long>;
const auto hash = [] (const el_type& element) {
    return std::hash<long>{}(std::get<0>(element)) ^
            (std::hash<long>{}(std::get<1>(element)) << 1) ^
            (std::hash<long>{}(std::get<2>(element)) << 2);
};

And that should be enough as long as the elements type have a viable == overload (so you don't have to provide custom equal function as well):

std::unordered_set<el_type, decltype(hash)> set{ 4, hash };
set.emplace(1, 2, 3); // std::pair<it, true> - inserted
set.emplace(0, 0, 1); // std::pair<it, true> - inserted
set.emplace(0, 0, 1); // std::pair<it, false> - insertion didn't happen
  • Related