The following valid program is rejected by gcc, clang and msvc. Only EDG accepts it correctly. https://godbolt.org/z/c9Wf8hh16 ``` struct C { C(const C&&) = default; // EDG: ok, gcc: No, Clang: No }; int main() { } ``` Gcc says: ``` <source>:3:4: error: defaulted declaration 'C::C(const C&&)' does not match the expected signature 3 | C(const C&&) = default; | ^ <source>:3:4: note: expected signature: 'constexpr C::C(C&&)' ```
Why do you think this is valid? https://eel.is/c++draft/class.copy.ctor#9 says implicitly declared move constructor has X::X(X&&) form and https://eel.is/c++draft/dcl.fct.def#default-2 defines rules under which the explicitly defaulted declaration can differ from the implicitly declared one. For copy constructors there is the https://eel.is/c++draft/dcl.fct.def#default-2.4 rule that if the implicitly declared would have const C & argument, the explicitly defaulted can have C & argument, but there is no such exception for && and it would need to be in the other direction anyway.
Or do you mean instead of error it should be just defined as deleted perhaps with warning per https://eel.is/c++draft/dcl.fct.def#default-2.6 ? In that case, I think clang implements it correctly and while GCC claims to implement https://wg21.link/p0641r2 it probably doesn't implement that fully or correctly.
CCing Marek who implemented CWG1331 aka this paper in r9-1200-g4db9ca8624e902b66
Yes, this is well-formed because the move ctor here is deleted as per 2.6 as explained in this thread: https://stackoverflow.com/a/78817438/12002570 In C++26, constructors have types through CWG2479 which is DRWP. In C+23 as published, ctors don't have types.
Not really sure if this paper was a DR or not. Seems clang rejects this for -std=c++17 and earlier and accepts with a warning for -std=c++20 and later, what we probably should do is silently make it deleted and when something attempts to use the deleted function, next to the normal diagnostics emit explanation why it was deleted.
Albuquerque 2017 doesn't mention it was a DR when voted in, so yes, C++20 or later I guess.
I have a patch implementing the clang++ behavior, that is, warning by default in C++20: 116162.C:3:4: warning: explicitly defaulted move constructor is implicitly deleted [-Wdefaulted-function-deleted] 3 | C(const C&&) = default; // EDG: ok, gcc: No, Clang: No | ^ 116162.C:3:4: note: function is implicitly deleted because its declared type does not match the type of an implicit move constructor
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:a2746e4347076ea48f4aeb28e13e6337ff7799ad commit r15-3721-ga2746e4347076ea48f4aeb28e13e6337ff7799ad Author: Marek Polacek <polacek@redhat.com> Date: Mon Sep 9 14:23:33 2024 -0400 c++: deleting explicitly-defaulted functions [PR116162] This PR points out the we're not implementing [dcl.fct.def.default] properly. Consider e.g. struct C { C(const C&&) = default; }; where we wrongly emit an error, but the move ctor should be just =deleted. According to [dcl.fct.def.default], if the type of the special member function differs from the type of the corresponding special member function that would have been implicitly declared in a way other than as allowed by 2.1-4, the function is defined as deleted. There's an exception for assignment operators in which case the program is ill-formed. clang++ has a warning for when we delete an explicitly-defaulted function so this patch adds it too. When the code is ill-formed, we emit an error in all modes. Otherwise, we emit a pedwarn in C++17 and a warning in C++20. PR c++/116162 gcc/c-family/ChangeLog: * c.opt (Wdefaulted-function-deleted): New. gcc/cp/ChangeLog: * class.cc (check_bases_and_members): Don't set DECL_DELETED_FN here, leave it to defaulted_late_check. * cp-tree.h (maybe_delete_defaulted_fn): Declare. (defaulted_late_check): Add a tristate parameter. * method.cc (maybe_delete_defaulted_fn): New. (defaulted_late_check): Add a tristate parameter. Call maybe_delete_defaulted_fn instead of giving an error. gcc/ChangeLog: * doc/invoke.texi: Document -Wdefaulted-function-deleted. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/defaulted15.C: Add dg-warning/dg-error. * g++.dg/cpp0x/defaulted51.C: Likewise. * g++.dg/cpp0x/defaulted52.C: Likewise. * g++.dg/cpp0x/defaulted53.C: Likewise. * g++.dg/cpp0x/defaulted54.C: Likewise. * g++.dg/cpp0x/defaulted56.C: Likewise. * g++.dg/cpp0x/defaulted57.C: Likewise. * g++.dg/cpp0x/defaulted58.C: Likewise. * g++.dg/cpp0x/defaulted59.C: Likewise. * g++.dg/cpp0x/defaulted63.C: New test. * g++.dg/cpp0x/defaulted64.C: New test. * g++.dg/cpp0x/defaulted65.C: New test. * g++.dg/cpp0x/defaulted66.C: New test. * g++.dg/cpp0x/defaulted67.C: New test. * g++.dg/cpp0x/defaulted68.C: New test. * g++.dg/cpp0x/defaulted69.C: New test. * g++.dg/cpp23/defaulted1.C: New test.
Should be fixed.