Skip to content

[dcl.fct.def.default] This can't apply to constructors as they don't have type #587

@ranaanoop

Description

@ranaanoop

Full name of submitter: Anoop Rana

Reference (section label): [dcl.fct.def.default]

Issue description:

The following program seem to be well-formed as per current standard wording as explained below. But only EDG accepts it while gcc,clang and msvc rejects it. Demo.

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

The explanation for why this seems to be well-formed is as following.

First note that C::C(const C&&) is a move ctor as per class.ctor:

A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments ([dcl.fct.default]).

Now we move onto dcl.fct.def.default where we see the condition for a function to be defaulted.

A function definition whose function-body is of the form = default ; is called an explicitly-defaulted definition.A function that is explicitly defaulted shall:

  • be a special member function[special] or a comparison operator function ([over.binary], [class.compare.default]), and

This means that if C(const C&&) = default; is either a a special member function or a comparison operator function then the program will be valid.

So we move onto special:

Default constructors ([class.default.ctor]), copy constructors,move constructors,copy assignment operators, move assignment operators ([class.copy.assign]), and prospective destructors ([class.dtor])are special member functions.

The above means that the move constructor C::C(const C&&)= default; is a special member function. Thus it can be defaulted and so the program is well-formed.

Now we move onto 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&.

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;
  • otherwise, the program is ill-formed.

As you can see dcl.fct.def.default#2.6 makes F1 deleted which means the program is well-formed.

But note the emphasis on the phrase "type of F1" and "type of F2" in dcl.fct.def.default#2.2. But in case F1 and F2 are ctors, what will the type of constructor mean as we know that constructors don't have type in C++. So how can this part of the above clause where the terms "type of F1" and "type of F2" is used supposed to be applicable to constructors. We need to define the meaning of type of a constructor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions