пн, 29 апр. 2019 г. в 21:08, Steven Watanabe
AMDG
On 4/29/19 12:04 PM, Antony Polukhin wrote:
пн, 29 апр. 2019 г. в 20:44, Steven Watanabe via Boost
: On 4/29/19 11:30 AM, Antony Polukhin via Boost wrote:
I've merged a very cool optimization by Nikita Kniazev into the master branch. From now on boost::variant does pointer stealing for recursive variants.
This significantly improves the performance of the variants move constructors.
However if you use a variant variable after the std::move for anything except destruction and assignment then you're getting an UB. Beware!
boost::variant goes to great lengths to prevent exactly this situation. You just broke it. This change is unacceptable. Please revert it. This optimization can be used iff. you have a way to construct a valid object in the rhs.
You can restore the old slow pre-rvalue era behavior by defining BOOST_VARIANT_NO_RECURSIVE_WRAPPER_POINTER_STEALING.
That doesn't make it okay. Look, this optimization would be fine with a different variant, one that doesn't provide the never-empty guarantee. That isn't boost::variant. <...>
From the theoretical point of view I'm on your side. boost::variant is something that is never-empty.
However, from the practical point of view : * noexcept(false) move constructor degrades performance of variant * move constructor that does a dynamic memory allocation is a surprise for the majority of users
From the teachers point of view... Boost is a collection of high quality libraries and many people look into the source codes to learn new tricks and correct approaches for solving problems. noexcept(false) move constructor that implicitly dynamically allocates is something that I would not prefer to show anyone.
From the C++ Standard Library point of view... Well, you can only assign new value or destroy a moved away variable. Everything is fine here.
3 against 1. I see a way to restore the theoretical beauty of the variant. We can just remove the empty() member function or force it to always return false. So that variant is still never empty, but using a variant after move is an UB. -- Best regards, Antony Polukhin