On Tue, 28 Oct 2025 at 16:13, Nikl Kelbon <kelbonage@gmail.com> wrote:
I dont see this as counter example. Its example of type, where move constructor does not guarantee... Any guarantees.

What? It guarantees that objects[this] will not be populated if the constructor fails.

 
So, its just correct behavior, where

1. variant not changed (still A)
2. B tried to construct and throws exception

The behaviour is not correct. I don't think you understood the example.
 

I think compiler who writes such beaty code must expect exactly such behavior 

No, because they expect that nobody will memcpy their objects around behind their back, because the objects are not trivially copyable.
 
The point is that if this throws, and you memcpy the A object back into place, the global registry of live objects has been modified. The "live" A object is no longer in the map.

A simpler version would be:

std::map<void*, std::type_info> live_objects;

A::A() {
  live_objects[this] = typeid(A);
}
~A::A() {
  assert(live_objects.contains(this));
  live_objects.erase(this);
}

B::B(B&&) {
  // any other object at this address must have been destroyed already:
  assert(!live_object.contains(this));
  live_objects[this] = typeid(B);
}

Now you don't even need B::B(B&&) to throw.

You memcpy the live A object to the side buffer, then construct B in the variant, and it fails the assertion, because the A object was not destroyed before you reused the memory.

Your idea quite simply breaks the C++ object model. You just keep insisting that it's OK, but it's not.



 

вт, 28 окт. 2025 г. в 20:58, Jonathan Wakely via Std-Proposals <std-proposals@lists.isocpp.org>:


On Tue, 28 Oct 2025 at 15:04, Pavel Vazharov via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Tue, Oct 28, 2025 at 4:46 PM Nikl Kelbon via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
>
> Thanks for the links, but I don't see any discussion of this particular idea there. Instead, they're discussing allocating the value on the heap or doubling the buffer.0308
The first sentence in the https://wg21.link/P0308 says
This paper argues in section III that when variant's contained types have noexcept move constructors, variant shall never be valueless, that is, the specification should statically guarantee that valueless_by_exception() will never return true.


Ah yes, but you see that paper didn't discuss the possibility of "just make it work for all types by using magic" ;-)


--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals