https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102912

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This is a bit of a mess. Previously we didn't construct the correct member of
the union in _-variant_construct_single, we just plopped an object in the
memory occupied by the union:

  void* __storage = std::addressof(__lhs._M_u);
  using _Type = remove_reference_t<decltype(__rhs_mem)>;
  ::new (__storage) _Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));

It didn't matter if we had variant<int, const int>, we would just place an int
(or const int) into the storage, and then set the _M_index to say which one it
was.

In the new constexpr-friendly code we use std::construct_at to construct the
union object, which constructs the active member of the right type. But now we
need to know exactly the right type. We have to distinguish between
alternatives of type int and const int, and we have to be able to find a const
int (or const std::string, as in the OP) among the alternatives. That's why my
change from remove_reference_t<decltype(__rhs_mem)> to remove_cvref_t<_Up> was
wrong. It strips the const from const int, and then we can't find the index of
the const int alternative.

But just using remove_reference_t doesn't work either. When the copy assignment
operator of std::variant<int> uses __variant_construct_single it passes a const
int& as __rhs_mem, but if we don't strip the const then we try to find const
int among the alternatives, and *that* fails.

The root cause of the problem is that __variant_construct_single doesn't know
the index of the type it's supposed to construct, and the new __index_of<_Type>
helper doesn't work if __rhs_mem and the alternative we're trying to construct
have different const-qualification. We need to replace
__variant_construct_single with something that has more type information
available.

Reply via email to