Let's say we store a struct with a string key and we want to find it by that string in a container like `std::set`, so common implementation would look like this:

```
struct Foo {
    std::string id;
};

struct FooComp {
    using is_transparent = std::true_type;

    bool operator()( const Foo &foo, const std::string &str ) const
    {
        return foo.id < str;
    }

    bool operator()( const std::string &str, const Foo &foo ) const
    {
        return str < foo.id;
    }

    bool operator()( const Foo &foo1, const Foo &foo2 ) const
    {
        return foo1.id < foo2.id;
    }
};

 std::set<Foo,FooComp> foo_set;
 ...

```

This works fine, but writing three methods for `FooComp` that do prety match the same (logically) is monotonic and error prone. Is there a way to minimize that code?