From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 6D6593858D35; Tue, 2 Nov 2021 12:36:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6D6593858D35 From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/102912] [12 Regression] Not full support of const arguments in std::variant Date: Tue, 02 Nov 2021 12:36:09 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Version: 12.0 X-Bugzilla-Keywords: rejects-valid X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: ASSIGNED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: redi at gcc dot gnu.org X-Bugzilla-Target-Milestone: 12.0 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Nov 2021 12:36:09 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D102912 --- Comment #2 from Jonathan Wakely --- 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 =3D std::addressof(__lhs._M_u); using _Type =3D remove_reference_t; ::new (__storage) _Type(std::forward(__rhs_mem)); It didn't matter if we had variant, 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 co= nst int (or const std::string, as in the OP) among the alternatives. That's why= my change from remove_reference_t 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 assign= ment operator of std::variant uses __variant_construct_single it passes a c= onst 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 kn= ow the index of the type it's supposed to construct, and the new __index_of<_T= ype> helper doesn't work if __rhs_mem and the alternative we're trying to constr= uct have different const-qualification. We need to replace __variant_construct_single with something that has more type information available.=