On Wed, 7 Sept 2022 at 16:30, Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Tue, Sep 6, 2022 at 1:34 PM Zhihao Yuan <zy@miator.net> wrote:
On Tuesday, September 6th, 2022 at 7:25 AM, Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
This is just std::visit. Here's the "very simple" version using the Null Object pattern (i.e., creating a new dummy subclass of IRS232 to represent "no connection"):
And here's the "less simple" version:

There are other ways to do it too, but std::visit seems like the simplest — and it's already present in C++17.
The logic is true, while the point of
this proposal was probably to allow
variant to return a pointer to its
own buffer without breaking the
type system.

My suggested use of `std::visit` doesn't "break the type system" as far as I can tell.

I conjecture that what ZY meant by this was that the implementation can bypass the overhead of switching on the index, forming a pointer to the derived object, and casting that to the base type, instead just forming a pointer to the base type directly from the buffer (assuming of course that the base type is indeed the first base and so has the same address in each alternative), while not resulting in UB from an invalid pointer cast.

But a modern implementation can eliminate the overhead anyway by looking through the call to std::visit; https://godbolt.org/z/a6o46TTbE compiles to an unimpeachable:

f(std::variant<std::monostate, D1, D2>&):
        xor     eax, eax
        cmp     BYTE PTR [rdi+1], 0
        cmovne  rax, rdi
        ret