Orient Orient - 11 months ago 46
C++ Question

Make std::set to use conversion operator when compare elements

Currently I use

to save key/value pairs:

#include <map>

using K = int;
struct P {}; // some useful payload

int main()
std::map< K, P const > m;
m.insert({1, {}});
auto it = m.find(1);
// access:

here is just for example.
is always
in my use case.

To access payload
P const
I have to use not too informative name
. The same regarding
. I want to name it simply
or somehow else.

To achieve this, I invent the following approach:

#include <set>

using K = int;
struct P {};

struct A
K key;
P payload;
operator K const & () const { return key; }

struct less
using is_transparent = void;
bool operator () (K const & l, K const & r) const
return l < r;

int main()
std::set< A, less > s;
s.insert({1, {}});
auto it = s.find(1);
// access:

Here I make
to use conversion operator every time for the key type. It works. But is it prohibited approach? Is there undefined behaviour?

Answer Source

To me, it looks technically valid.

But it also falls into the category of "making your code so unnecessarily complex that a programmer has to look twice or thrice at it before they comprehend what on earth you're doing, and can validate that you're doing it correctly, and for basically no tangible benefit" which is very ungood.

Indeed, the fact that you — the code's own author, no less! — felt the need to come here asking for a language lawyer to validate the code's correctness is a big red flag that this is likely not worthwhile.

If at any point you feel that .first and .second are insufficiently descriptive for your code, you can instead get around that locally with such magic as:

auto& key     = it->first;
auto& payload = it->second;

or even:

auto& payload = getPayload(it);

where getPayload is an appropriate function taking an iterator of your particular type.

These approaches have the benefit of being fairly obvious, and of not requiring convening a session of the C++ Supreme Court to check them over first.