From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 1F7FC3858CDB; Sun, 30 Jul 2023 14:05:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F7FC3858CDB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1690725942; bh=1cDsrXhdlTzBRY+MaYkX7YNhUULWX+etpbznbcjvNZ0=; h=From:To:Subject:Date:From; b=TaXCZgVJ3JmGlBSuFhjS8kyXXogi81vseLifxUNZPs38pslMdTmzRyJhR3vjQLPbL I2o8G0vMdyqbM4HUa2s/u6NtgucrlCqHPdmXELF5zYtICsiXulh8TlQliX+BNw79Xc 0x0xcU7rDkrVwUOK0j4oPg9DhDz9dxD+pW1O04+I= From: "daniel.kruegler at googlemail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/110853] New: [c++-concepts] Bad interaction between deduction guide with decay and constraints Date: Sun, 30 Jul 2023 14:05:41 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 14.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: daniel.kruegler at googlemail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: 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 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D110853 Bug ID: 110853 Summary: [c++-concepts] Bad interaction between deduction guide with decay and constraints Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: daniel.kruegler at googlemail dot com Target Milestone: --- The following simplified code snippet demonstrates a breakage our company c= ode when updating gcc from C++17 to C++20. I'm starting first with the original example, because it provides a bit more context information: ------------------------------------ #include void value_twice(int& result) { result =3D 2 * result; } auto key_value_gen() { return std::pair("key", value_twice); } int main() { } ------------------------------------ Using gcc HEAD 14.0.0 20230728 and compiled with the previous settings -Wall -Wextra -pedantic -std=3Dc++17 the code is accepted, but switching to -Wall -Wextra -pedantic -std=3Dc++20 it becomes rejected with the following diagnostics: ------------------------------------ In file included from /opt/wandbox/gcc-head/include/c++/14.0.0/utility:69, from prog.cc:1: /opt/wandbox/gcc-head/include/c++/14.0.0/bits/stl_pair.h: In instantiation = of 'struct std::pair': /opt/wandbox/gcc-head/include/c++/14.0.0/bits/stl_pair.h:307:57: required= by substitution of 'template pair(const _T1&, const _T2&= )-> std::pair<_T1, _T2> requires (std::pair<_T1, _T2>::_S_constructible)() [with _T1 =3D char [4]; _T2 =3D void(int&)]' prog.cc:10:38: required from here /opt/wandbox/gcc-head/include/c++/14.0.0/bits/stl_pair.h:194:11: error: data member 'std::pair::second' invalidly declared function type 194 | _T2 second; ///< The second member | ^~~~~~ ------------------------------------ Note that std::pair has a "decaying" deduction guide template pair(T1, T2) -> pair; but the error message reveals that attempts the produce a std::pair of the undecayed types. Additional information: a) Current MSVC accepts the code but clang also rejects it but for different reasons than gcc (see below). b) I'm aware that a simple workaround exists by returning std::pair("key", &value_twice) instead, and this is what we did to fix this. Nonetheless I t= hink that not everyone is able to fix such a problem in similar code when it was provided by thirdparty libraries. Basically the same error occurs when we use std::tuple(value_twice) instead. The C++20 std::pair implementation uses noexcept, conditional explicit, and trailing requires-clause based on static member functions as predicates, but for gcc the problem can be reduced to the trailing requires-clause alone: -------------------------------------- #define WITH_FUNC 1 template constexpr bool is_copy_constructible_v =3D true; template struct p { T1 first; static constexpr bool do_is_copy_constructible() { return true; } p(const T1& t1)=20 requires ( #if WITH_FUNC do_is_copy_constructible() // Line 19 #else is_copy_constructible_v #endif ) : first(t1)=20 {} }; template p(T1) -> p; void value_twice(int& result) { result =3D 2 * result; } auto value_gen() { return p(value_twice); // line 38 } int main() {} -------------------------------------- If we define WITH_FUNC to 0, the code is accepted, otherwise (as shown abov= e), the code is rejected with: -------------------------------------- prog.cc: In instantiation of 'struct p': prog.cc:19:31: required by substitution of 'template p(const T1= &)-> p requires (p::do_is_copy_constructible)() [with T1 =3D void(int&)]' prog.cc:38:23: required from here prog.cc:9:6: error: data member 'p::first' invalidly declared function type 9 | T1 first; | ^~~~~ -------------------------------------- Note that clang does accept the reduced case, even though it rejects the original example as well due to slightly different reasons, which I will re= port separately to them. The reduced case uses the same implementation strategy as libstdc++ by mean= s of a static member function. What's special here is that the body of such a function is a complete-class context of p, which I guess causes the error h= ere because the trailing requires-clause is not a complete-class context of p, = so one could say that this is actually a libstdc++ defect to use this implementation strategy, it seems odd to me that the compiler attempts to instantiate p with the undecayed function here and would like to open this initially as compiler defect since the corresponding function does not actu= ally depend on p being complete. Feel free to correct me, but in case of a correction of my understanding I would like to change this to a libstdc++ i= ssue instead of closing it because that would mean that libstdc++ cannot use the= re static member function predicate approach (A free function template could be used instead of a static member function, I tested that).=