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.