Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dcl.init.general] Fix the informative description in 16.6.1 Example 2 CWG2612 #5489

Conversation

frederick-vs-ja
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja commented May 24, 2022

T x = T(T(T())); value-initializes x, and according to [dcl.init.general]/(9.1.2), the initialization (when well-formed) skips the constructor call if the default constructor is trivial.

Fixes #5488.

@JohelEGP
Copy link
Contributor

The redundant T(s can go, too, since this isn't about copy ellision.

@xmh0511
Copy link
Contributor

xmh0511 commented May 24, 2022

@JohelEGP The multi-level T( intends to expose that prvalue of the same class type does not create the temporary object, instead it delays initializing its result object.

@jensmaurer
Copy link
Member

I think it's unobservable whether a trivial default constructor is called or not.

@xmh0511
Copy link
Contributor

xmh0511 commented May 24, 2022

I think it's unobservable whether a trivial default constructor is called or not.

The prvalue does value-initialize its result object. Based on this precondition, whether the object is default-initialized or zero-initialized depends on the rules defined in [dcl.init.general] p9.

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type ([class]), then
  • if T has either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
  • otherwise, the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

To value-initialize an object of class T, the initialization is either zero-initialization or default-initialization. Only in the default-initialization case, the default constructor will be called.

The comment just says the object will be initialized by the default constructor, which is just wrong. I think it is observable if the object is used in a constant expression.

struct T{
    int a;
};
constexpr T obj = T();  //ok
constexpr T obj2; // error

The reason for the error at obj2 is the same as that of the example in #5422

@jensmaurer
Copy link
Member

The constexpr question is CWG2536 and maybe CWG2558.

@xmh0511
Copy link
Contributor

xmh0511 commented May 24, 2022

The constexpr question is CWG2536 and maybe CWG2558.

I meant we can observe whether the default constructor is called in this case. The issue is that the comment arbitrarily says the default constructor is called for x. However, the value-initialization of x is not necessarily the default-initialization, may be zero-initialization, which can initialize T::a to 0, which is not uninitialized.

@frederick-vs-ja
Copy link
Contributor Author

frederick-vs-ja commented May 24, 2022

To value-initialize an object of class T, the initialization is either zero-initialization or default-initialization. Only in the default-initialization case, the default constructor will be called.

Isn't 9.1.2 indicating that both zero-initialization and default-initialization are performed if the default constructor is defaulted and non-trivial?

msvc accepts the following example, while gcc, icc, and clang rejects it (link).

struct Foo {
    int a;
    int b = 1;
};

static_assert(Foo().a == 0);

IIUC, msvc is doing the right thing here.


I think it's unobservable whether a trivial default constructor is called or not.

Yes. However, if it's confirmed that a trivial default constructor is not needed to skip, can we simplify [dcl.init.general]/(9.1.2) as following?

otherwise, the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is then default-initialized;

And I still think "value-initializes" should be used, because both zero- and default-initialization may matter when both are present.

@xmh0511
Copy link
Contributor

xmh0511 commented May 25, 2022

Isn't 9.1.2 indicating that both zero-initialization and default-initialization are performed if the default constructor is defaulted and non-trivial?

Seems that you're right. GCC and Clang might have a misreading here. It might also be the intent here is that the value-initialization of an object of class type(its default constructor is defaulted and non-trivial) is either zero-initialized or default-initialized but not both? GCC and Clang implement the right things just didn't embody them in the current wording?

@frederick-vs-ja
Copy link
Contributor Author

Seems that you're right. GCC and Clang might have a misreading here. It might also be the intent here is that the value-initialization of an object of class type(its default constructor is defaulted and non-trivial) is either zero-initialized or default-initialized but not both? GCC and Clang implement the right things just didn't embody them in the current wording?

Perhaps a CWG issue is needed. I've opened cplusplus/CWG#40 for this (and possibly another issue touching the same paragraph).

@tkoeppe
Copy link
Contributor

tkoeppe commented Aug 22, 2022

Can we close this issue in favour of the CWG issue then?

@jensmaurer
Copy link
Member

The core issue hasn't been created, yet.

@xmh0511
Copy link
Contributor

xmh0511 commented Aug 23, 2022

The core issue hasn't been created, yet.

Created a CWG issue in cplusplus/CWG#117

@jensmaurer
Copy link
Member

No. That's the inbox for new core issues, not the actual core issues list.

@jensmaurer jensmaurer added the cwg Issue must be reviewed by CWG. label Aug 23, 2022
@jensmaurer
Copy link
Member

See CWG2612

@jensmaurer jensmaurer changed the title [dcl.init.general] Fix the informative description in 16.6.1 Example 2 [dcl.init.general] Fix the informative description in 16.6.1 Example 2 CWG2612 Aug 24, 2022
@frederick-vs-ja
Copy link
Contributor Author

Done in #5984. Closing.

@frederick-vs-ja frederick-vs-ja deleted the value-init-no-default-ctor branch March 2, 2023 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cwg Issue must be reviewed by CWG.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The comment of the example in [dcl.init.general] p16.6.1 is wrong CWG2612
5 participants