Skip to content

Conversation

@N-Dekker
Copy link
Contributor

@N-Dekker N-Dekker commented Nov 5, 2025

Clarified that the Enforcement of C.45: Don't define a default constructor that only initializes data members... is specifically about user-defined non-defaulted default constructors.

Clarified that the Enforcement of "C.45: Don't define a default constructor that only initializes data members..." is specifically about _user-defined non-defaulted_ default constructors.
@N-Dekker N-Dekker marked this pull request as ready for review November 5, 2025 21:10
@hsutter hsutter closed this in f52da2b Dec 3, 2025
@hsutter
Copy link
Contributor

hsutter commented Dec 3, 2025

Editors call: Thanks! We decided to reword it a bit further, and thanks for pointing out it needed to be more precise.

##### Enforcement

(Simple) A default constructor should do more than just initialize data members with constants.
(Simple) A user-defined non-defaulted default constructor should do more than just initialize data members with constants.
Copy link
Contributor Author

@N-Dekker N-Dekker Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hsutter Thank you for reviewing my pull request. I'm very interested to see your rewording of this enforcement! Maybe you could just use the informal term "hand-written", rather than my proposed "user-defined non-defaulted" default constructor...?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard has a term for exactly this:

[A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jwakely I like the term "user-provided". However I think it's important to still add the term "non-defaulted" as well, in this particular Enforcement. As in:

"A user-provided non-defaulted default constructor should do more than just initialize data members with constants."

Because as far as I can see, it is OK for a user-provided defaulted default constructor to just initialize data members with constants. (It may still be defaulted after its first declaration.) Right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that the distinction really matters here, and the sentence gets harder to read with more terminology you squeeze into it.

Arguably, a function that is defaulted outside the class (i.e. not on its first declaration) does do more than just init members: it provides a non-inline definition of the symbol, which might be needed to preserve the library's ABI, or break a circular dependency by defining it after some other class is complete.

So that would be OK. A user-provided default constructor should either perform some non-trivial logic that can't be done by simple default member initializers, or it should accomplish something else that can't be done by defaulting it on first declaration.

Anyway, Herb's commit removes the term entirely. I don't think the word "explicit" in that commit adds any value though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, the enforcement appears quite different now, after Herb's commit (f52da2b):

(Simple) Flag if a default constructor's explicit member initializer is a constant, and recommend that the constant should be written as a data member initializer instead.

I thought the original intention of this specific enforcement was: avoiding that programmers manually write default-constructors that can be defaulted instead (while still having the same behavior). Originally, the enforcement would ignore default-constructors that do other things than just initializing data members, for example:

class MyClass
{
public:
    MyClass()
    : data{ 42 }
    {
        std::cout << "Doing more than just initializing data!";
    }

private:
    int data;
};

(In this example, the original enforcement would only get triggered after removing the print statement.)

string s {"default"};
int i {1};
public:
// use compiler-generated default constructor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be an improvement to explicitly default the default ctor in the "good" example? That's needed if there are any other ctors declared (e.g. a copy or move ctor), and is more explicit about the intention.

Suggested change
// use compiler-generated default constructor
X() = default;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants