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.

Reply via email to