Gcc and clang reject move constructor with =default
Asked Answered
B

1

6

I wrote the following program that compiles with EDG but is rejected by gcc, clang and msvc. Demo

struct C
{
   C(const C&&) = default; // EDG: ok, gcc: No, Clang: No
};
int main()
{
    
}

Afaik this should compile but all three major compilers rejects it. Only edg accept it. I want to know what is the standard conformant behavior here.

For reference, 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&&)'
Belk answered 31/7 at 16:17 Comment(13)
@CoryKramer No, I don't think that is true. C::C(const C&&) is also a move ctor.Guffaw
Looks well-formed to me. Only EDG got this right.Guffaw
@CoryKramer No, see carefully that link you gave, it says there "single-parameter-list - a parameter list of only one parameter, which is of type T&&, const T&&". GCC, clang and msvc are wrong in giving a diagnostic here.Guffaw
@Someprogrammerdude Though the tag seems to indicate OP is looking for C++23. The compiler versions need not be specified.Guffaw
@Gene You missed the fact that this is not an implicity-move ctor. It is explicitly default ctor. See "An implicitly-declared special member function is declared at the closing } of the class-specifier . Programs shall not define implicitly-declared special member functions."Guffaw
@Guffaw -- 9.5.2/2 specifies how explicitly defaulted special member function can differ from special member function, different constness only allowed for lvalue reference.Complement
@Complement Post the link/reference. Otherwise it not clear which point you're referring to.Guffaw
@Guffaw -- here is the link: timsong-cpp.github.io/cppwp/dcl.fct.def.default#2Complement
@Someprogrammerdude OP is using the latest version of all the said compilers in their link. I don't see mentioning compiler versions as a requirement for posting question specially when a MRE is available and link to code is available.Guffaw
cppreference move ctor also explains this to be valid.Guffaw
@Guffaw -- the second paragraph clear that if you default const version it's deleted.Complement
@Guffaw -- timsong-cpp.github.io/cppwp/dcl.fct.def.default#2.6 : "otherwise, if F1 is explicitly defaulted on its first declaration, it is defined as deleted;"Complement
@Complement Constructors now do have type so this becomes well-formed now as per dcl.fct.def.default#2.6 as the move ctor will just be deleted. Note as published, in C++23 ctor didn't have type.Guffaw
G
6

The program is well-formed as per dcl.fct.def.default#2.6 which is applicable when none of the first four bullets in dcl.fct.def.default are satisfied. So we move onto the latter part which says if F1 is explicitly defaulted on its first declaration, it will be defined as deleted. Note that this change was made by P0641R2 which made C(const C&&) = default; deleted instead of ill-formed. So the program is well-formed.

Note also that CWG2476 allowed constructors to have a type as explained in Can constructors have type.


Now, from dcl.fct.def.default:

An explicitly defaulted special member function F1 is allowed to differ from the corresponding special member function F2 that would have been implicitly declared, as follows:

  • F1 and F2 may have differing ref-qualifiers;
  • if F2 has an implicit object parameter of type “reference to C”, F1 may be an explicit object member function whose explicit object parameter is of (possibly different) type “reference to C”, in which case the type of F1 would differ from the type of F2 in that the type of F1 has an additional parameter;
  • F1 and F2 may have differing exception specifications; and
  • if F2 has a non-object parameter of type const C&, the corresponding non-object parameter of F1 may be of type C&.

As we can see none of the above four bullet points apply. So we move onto the next part that says:

If the type of F1 differs from the type of F2 in a way other than as allowed by the preceding rules, then:

  • if F1 is an assignment operator, and the return type of F1 differs from the return type of F2 or F1's non-object parameter type is not a reference, the program is ill-formed;
  • otherwise, if F1 is explicitly defaulted on its first declaration, it is defined as deleted;

As you can see the move ctor C::C(const C&&) should be defined as deleted.

Guffaw answered 31/7 at 16:25 Comment(10)
@Complement [eel.is/c++draft/dcl.fct.def.default#2] does seem to make this ill-formed. Updating.Guffaw
@Complement Updated. . Thanks for the correction. But note the problem with "type of ctor" is still there in the latter part which is not used here.Guffaw
@Complement Non-object parameter is actually the correct term in 2.4 because it is also talking about implicitly declared ctor and the explicitly defaulted ctor as in my example which have only non-object parameter. They don't have object parameter in the first place.Guffaw
@Complement For example, take struct C{C(const C&);};. The copy ctor here has only non-object parameter. Gotta go to sleep now. It's late night here or very early morning.Guffaw
@Alan No. Those bullets are ways in which the explicit declaration is allowed to differ from the implicit declaration. Your explicit version doesn't differ from the implicit one.Conventicle
@Complement Turns out this is actually well-formed as per dcl.fct.def.default#2.6 because constructors do have types through the mentioned CWG in my answer.Guffaw
@Ext3h As published, in C++23 ctors don't have type. But through CWG2479 they do have type. So this program is well-formed. See the updated answer.Guffaw
@NathanOliver This is indeed well-formed as now ctors have a type and the move ctor here is deleted as per [dcl.fct.def.default#2.6]. Check out the updated answer.Guffaw
So, it can't be decided if it's ill-formed or well-formed, the answer is changed every few hours.Major
@Major It's decided that it is well-formed. See confirmed gcc bug which has already been assigned, as gcc rejects this incorrectly.Guffaw

© 2022 - 2024 — McMap. All rights reserved.