Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spaceship operator with pimpl idiom

I have a class that uses the pimpl idiom.

class MyImpl;

class MyClass
{
public:

private:
    MyImpl* _impl;
};

Now I'd like to add spaceship operator support to this class. Ideally I would write something like:

auto operator<=>(const MyClass& rhs) const
{
    return *_impl <=> *rhs._impl;
}

The implementation is not known in the header file though. Hence, I have to write the implementation in the source file. But that prevents the usage of auto as a return type. I have to be explicit on whether it's std::strong_ordering, std::weak_ordering or std::partial_ordering. But that heavily depends on the details of MyImpl. If MyImpl contains only ints, the return type would be std::strong_ordering, but if it would contain floats too it would be std::partial_ordering.

I'd like the class declaration of MyClass not to change too much. What's a way to keep its api stable, while still allowing changing member types of MyImpl. I guess it's not ideal to just always return std::partial_ordering.

like image 323
Tohnmeister Avatar asked Feb 07 '26 13:02

Tohnmeister


1 Answers

But that heavily depends on the details of MyImpl.

No, it doesn't.

I mean yes, in a literal in-code sense, the details of the comparison are determined by MyImpl. But the comparison category of a type is not a private element of that type. It's a public interface, and that public interface needs to be defined.

In its entirety.

This is no different from any public member of a Pimpl'd type. If the type has a public interface and a private implementation, the two functions must be in sync. Any changes to one must be propagated to the other.

C++ Pimpl is not DRY. Indeed, it often involves a lot of redundancy. That's just the nature of the idiom.

If MyImpl contains only ints, the return type would be std::strong_ordering, but if it would contain floats too it would be std::partial_ordering.

And you have therefore changed the public interface of that class. You have changed when and how the user can compare instances of that type.

This is not a private matter, so the public interface needs to change accordingly.

like image 51
Nicol Bolas Avatar answered Feb 09 '26 07:02

Nicol Bolas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!