I am working with std::unordered_set
of CustomKey
objects and I am thinking about how to complicate my life.
I already know the idiomatic ways of using custom Hash and EqualKey. For custom Hash it's possible to implement a class that overrides the operator()
or a custom specialization of std::hash
(which could be also injected in the namespace std). For a custom EqualKey it's possible to implement a class that overrides the operator()
or a specialization of std::equal
, or an overload of operator==()
of CustomKey.
I wrote that I complicate my life because I am exploring alternative ways for custom Hash and EqualKey, in the spirit of this other question of mine
I defined these three custom Hashes inside CustomKey
class:
static size_t CustomKey::ClassStaticHash(const CustomKey& doubleStringKey) {...}
size_t CustomKey::ClassNonStaticHash() const {...}
class CustomKey::ClassClassHash
{
public:
size_t operator()(const CustomKey& myCustomKey) const {...}
};
and these three outside:
size_t CustomFunctionHash(const CustomKey& myCustomKey) {...}
auto CustomLambdaHash = [](const CustomKey& myCustomKey) {...};
class CustomClassHash
{
public:
size_t operator()(const CustomKey& myCustomKey) const {...}
};
In a similar way, I defined these three custom EqualKeys inside CustomKey
class
static bool CustomKey::ClassStaticEqual(CustomKey const& lhs, CustomKey const& rhs) {...}
bool CustomKey::ClassNonStaticEqual(const CustomKey& other) const {...}
class CustomKey::ClassClassEqual
{
public:
bool operator()(const CustomKey& lhs, const CustomKey& rhs) const {...}
};
and these three outside:
bool CustomFunctionEqual(const CustomKey& firstCustomKey,
const CustomKey& secondCustomKey) {...}
auto CustomLambdaEqual = [](const CustomKey& firstCustomKey,
const CustomKey& secondCustomKey) {...};
class CustomClassEqual
{
public:
bool operator()(const CustomKey& firstCustomKey,
const CustomKey& secondCustomKey) const {...}
};
As for now, I managed to define an unordered_set
for all the single custom Hash and for half of the 36 combinations of the 6 custom Hash and the 6 custom EqualKey.
Instead of providing a detailed list, which would be devastating for you to read, I opt for dividing all the cases in six sets, illustrate what I was able to do and ask what I had problem with.
So, let's go!
First problem
For what concerns CustomKey::ClassNonStaticHash
, I defined two templates:
template <class T, class Hash>
std::unordered_set<T, Hash> make_unordered_set(Hash&& hash)
{
return std::unordered_set<T, Hash>{10, std::forward<Hash>(hash)};
}
template <class T, class Hash, class KeyEqual>
std::unordered_set<T, Hash, KeyEqual> make_unordered_set(Hash&& hash, KeyEqual&& keyequal)
{
return std::unordered_set<T, Hash, KeyEqual>{10, std::forward<Hash>(hash), std::forward<KeyEqual>(keyequal)};
}
and I can instantiate both an unordered_set
with only CustomKey::ClassNonStaticHash
auto my_unordered_set = make_unordered_set<CustomKey>(std::mem_fn(&CustomKey::ClassNonStaticHash))
and an unordered_set
with CustomKey::ClassNonStaticHash
and CustomKey::ClassNonStaticEqual
auto my_unordered_set = make_unordered_set<CustomKey>(std::mem_fn(&CustomKey::ClassNonStaticHash), std::mem_fn(&CustomKey::ClassNonStaticEqual));
I have tried to implement other templates, but they did not work and I don't understand how to instantiate an unordered_set
with the other combinations, namely with CustomKey::ClassNonStaticHash
and respectively CustomKey::ClassStaticEqual
, or CustomKey::ClassClassEqual
, or CustomFunctionEqual
, or CustomLambdaEqual
, or CustomClassEqual
Second problem
For what concerns CustomKey::ClassStaticHash
, I am able to define all but one unordered_set
. For example, for the combination with CustomLambdaEqual
,and similarly with all others but CustomKey::ClassNonStaticEqual
, I have:
typedef std::function<size_t(const CustomKey&)> Hash;
std::unordered_set<CustomKey, Hash, decltype(CustomLambdaEqual)> my_unordered_set{10, Hash(&CustomKey::ClassStaticHash), CustomLambdaEqual};
The problem is with the combination of CustomKey::ClassStaticHash
and CustomKey::ClassNonStaticEqual
. How could I instantiate an unordered_set
with CustomKey::ClassStaticHash
and CustomKey::ClassNonStaticEqual
?
Third problem
For what concerns CustomKey::ClassClassHash
, I can easily instantiate:
std::unordered_set<CustomKey, CustomKey::ClassClassHash> my_unordered_set;
I can also easily instantiate the combination of CustomKey::ClassClassHash
and CustomKey::ClassClassEqual
std::unordered_set<CustomKey, CustomKey::ClassClassHash, CustomKey::ClassClassEqual> my_unordered_set;
and the combination of CustomKey::ClassClassHash
and CustomClassEqual
std::unordered_set<CustomKey, CustomKey::ClassClassHash, CustomClassEqual> my_unordered_set;
The problem is with the combinations of CustomKey::ClassClassHash
and respectively CustomKey::ClassStaticEqual
, or CustomKey::ClassNonStaticEqual
, or CustomFunctionEqual
or CustomLambdaEqual
. The main reason is that I don't understand how to specify CustomKey::ClassClassHash
in the template parameters and the various EqualKeys in the parameter of the constructor.
Fourth and fifth problem
For what concerns CustomFunctionHash
and CustomLambdaHash
, the problem is very similar.
In both cases I don't understand how to instantiate unordered_set
for the combination with ClassNonStaticEqual
.
Sixth problem
For what concerns CustomClassHash
, I can easily instantiate an unodered_set
with CustomKey::ClassClassEqual
std::unordered_set<CustomKey, CustomClassHash, CustomKey::ClassClassEqual> my_unordered_set;
and with CustomClassEqual
std::unordered_set<CustomKey, CustomClassHash, CustomClassEqual> my_unordered_set;
The problem, here, is with the combinations with CustomKey::ClassStaticEqual
, or CustomKey::ClassNonStaticEqual
, or CustomFunctionEqual
or CustomLambdaEqual
. The main reason is similar to the third problem: I don't understand how to specify CustomClassHash
in the template parameters and the various EqualKeys in the parameter of the constructor.
I repeat that I am aware that there are idiomatic ways to use unordered associative containers like unordered_set
. The main reason why I am asking about these combinations is to ask for a feedback about how to play with templates.
I will truly appreciate every effort of those who will have the patience to read and help.