On 03/04/19 17:25 +0100, Jonathan Wakely wrote:
Avoid creating arbitrarily large objects on the stack when creating
temporaries in order to provide the strong exception-safety guarantee.
Also implement Antony Polukhin's suggestion to whitelist specific types
that can be efficiently move-assigned, so that emplacing those types
never causes a variant to become valueless. The whitelisted types are:
all trivially copyable types no greater than 256 bytes in size,
std::shared_ptr, std::weak_ptr, std::unique_ptr, std::function, and
std::any. Additionally, std::basic_string, std::vector, and
__gnu_debug::vector are whitelisted if their allocator traits give them
a non-throwing move assignment operator. Specifically, this means
std::string is whitelisted, but std::pmr::string is not.
PR libstdc++/87431 (again)
* include/bits/basic_string.h (__variant::_Never_valueless_alt):
Define partial specialization for basic_string.
* include/bits/shared_ptr.h (_Never_valueless_alt): Likewise for
shared_ptr and weak_ptr.
* include/bits/std_function.h (_Never_valueless_alt): Likewise for
function.
* include/bits/stl_vector.h (_Never_valueless_alt): Likewise for
vector.
* include/bits/unique_ptr.h (_Never_valueless_alt): Likewise for
unique_ptr.
* include/debug/vector (_Never_valueless_alt): Likewise for debug
vector.
* include/std/any (_Never_valueless_alt): Define explicit
specialization for any.
* include/std/variant (_Never_valueless_alt): Define primary template.
(__never_valueless): Use _Never_valueless_alt instead of
is_trivially_copyable.
(variant::emplace<N>(Args&&...)): Add special case for non-throwing
initializations to avoid try-catch overhead. Add special case for
scalars produced by potentially-throwing conversions. Use
_Never_valueless_alt instead of is_trivially_copyable for the
remaining strong exception-safety cases.
(variant::emplace<N>(initializer_list<U>, Args&&...)): Likewise.
* testsuite/20_util/variant/87431.cc: Run both test functions.
* testsuite/20_util/variant/exception_safety.cc: New test.
* testsuite/20_util/variant/run.cc: Use pmr::string instead of string,
so the variant becomes valueless.
I'd like to commit this to trunk this week. Does anybody see any
problems with this approach?
I've committed this patch.
We can still consider whitelisting other types until the GCC 9
release, but we should do it soon.