https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85517
Bug ID: 85517 Summary: std::variant exception safety problems Product: gcc Version: 7.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: zhangxy at google dot com Target Milestone: --- There are several issues with the implementation of std::variant related to exception safety: 1. Copy assignment According to [variant.assign] 23.7.3.3 (2.4): if either is_nothrow_copy_constructible_v<Tj> or !is_nothrow_move_constructible_v<Tj> is true, equivalent to emplace<j>(get<j>(rhs)). Failure case 1) If Tj is nothrow copy constructible, it should be equivalent to emplace() which destroys the current content and invoke Tj's copy ctor. However, the current implementation always copy constructs a temporary variant and invoke the move constructor. This is unnecessary. Failure case 2) If Tj's copy ctor throws, *this should be valueless_by_exception() because emplace() first destroys then invokes the copy ctor. Since the current implementation copy constructs a temporary variant first, it has strong guarantee while the standard requires basic guarantee. 2. Conversion assignment operator=(T&&) According to [variant.assign] 23.7.3.3 (11.3): if is_nothrow_constructible<Tj, T> == false && is_nothrow_move_constructible<Tj> == true, equivalent to operator=(variant(std::forward<T>(t))). Failure case: If Tj has a nothrow move constructor, the standard requires strong guarantee (that a temporary variant be created first and move it into *this). The current implementation always invokes emplace(), which has only basic guarantee.