Date: Fri, 25 Feb 2022 13:13:11 -0500
Arthur,
I've learned to never disagree with you on anything, so I'd like to be correctly corrected :-)
I've always been under the understanding that reordering was only granted ACROSS access control boundaries, but everything within the same access boundary had a strict ordering.
Here is the wording from the C++20 standard, though I don't think it has changed much over the years...
• 19 [Note: Non-static data members of a (non-union) class with the same access control (11.9) and non-zero size (6.7.2) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified. Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (11.7.2) and virtual base classes (11.7.1). —end note]
The "higher addresses" does not necessarily mean consecutive, but I'd find it difficult to see how the compiler could arrange a and b in your example in a different order and still meet this requirement, since they have the same access control level.
Thanks.
> On Feb 25, 2022, at 10:57 AM, Arthur O'Dwyer via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> On Fri, Feb 25, 2022 at 1:57 AM Chris Ryan via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
> >" The choice of allowing you to specify members in the member
> initialization list out of order from their order of initialization?
> Honestly, I have no idea why that was ever legal."
>
> Quickly looking I could not find the reference for it but I did not think that it was ever legal.
> Most every compiler I tested (on godbolt) did report it as a warning (-Wreorder) with -Wall or /Wall.
> "Initializer order does not match the declaration order" or something like that depending on your compiler
>
> Yes, but the reason that the compiler gives you a warning is because the construct is (for some reason) legal C++ that the compiler must accept (despite being never-what-you-wanted). If the construct were actually forbidden by the standard, then you'd get an error instead, even without -Wall.
>
> (Also, pedantic nit: IIRC, I believe MSVC's equivalent of -Wall is -W4; their -Wall is actually the equivalent of Clang's -Weverything.)
>
>
> You [can] have many constructors [...] but only one destructor and it needs to use the reverse order (of declaration).
> If the destructor must be in reverse order of declaration, construction must be in order of declaration.
>
> Yup, exactly!
>
> I vaguely wonder if the original reason for permitting the programmer to write
> struct S {
> explicit S() : b(1), a(2) {}
> private:
> int a;
> int b;
> };
> (and the compiler to silently reorder the initializers) was somehow also related to C++'s permission for the compiler to silently reorder the layout of `a` and `b` in memory (because this is not a standard-layout class). No compiler has ever actually done that, and IIRC the permission to reorder memory layouts has been proposed-to-be-revoked and maybe even scaled back in C++23.
> It's kind of the same idea, from the 1990s point of view: Instead of forcing the programmer to write everything in the "correct" order like bad old C, let's permit the programmer to write in whatever order they like, and then the compiler can magically fix it up! Hooray C++!
> It's only after like 20 years of that stuff that enough people are publicly saying "well, this is confusing; we should just force the programmer to write what they mean."
>
> –Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
I've learned to never disagree with you on anything, so I'd like to be correctly corrected :-)
I've always been under the understanding that reordering was only granted ACROSS access control boundaries, but everything within the same access boundary had a strict ordering.
Here is the wording from the C++20 standard, though I don't think it has changed much over the years...
• 19 [Note: Non-static data members of a (non-union) class with the same access control (11.9) and non-zero size (6.7.2) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified. Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (11.7.2) and virtual base classes (11.7.1). —end note]
The "higher addresses" does not necessarily mean consecutive, but I'd find it difficult to see how the compiler could arrange a and b in your example in a different order and still meet this requirement, since they have the same access control level.
Thanks.
> On Feb 25, 2022, at 10:57 AM, Arthur O'Dwyer via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> On Fri, Feb 25, 2022 at 1:57 AM Chris Ryan via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
> >" The choice of allowing you to specify members in the member
> initialization list out of order from their order of initialization?
> Honestly, I have no idea why that was ever legal."
>
> Quickly looking I could not find the reference for it but I did not think that it was ever legal.
> Most every compiler I tested (on godbolt) did report it as a warning (-Wreorder) with -Wall or /Wall.
> "Initializer order does not match the declaration order" or something like that depending on your compiler
>
> Yes, but the reason that the compiler gives you a warning is because the construct is (for some reason) legal C++ that the compiler must accept (despite being never-what-you-wanted). If the construct were actually forbidden by the standard, then you'd get an error instead, even without -Wall.
>
> (Also, pedantic nit: IIRC, I believe MSVC's equivalent of -Wall is -W4; their -Wall is actually the equivalent of Clang's -Weverything.)
>
>
> You [can] have many constructors [...] but only one destructor and it needs to use the reverse order (of declaration).
> If the destructor must be in reverse order of declaration, construction must be in order of declaration.
>
> Yup, exactly!
>
> I vaguely wonder if the original reason for permitting the programmer to write
> struct S {
> explicit S() : b(1), a(2) {}
> private:
> int a;
> int b;
> };
> (and the compiler to silently reorder the initializers) was somehow also related to C++'s permission for the compiler to silently reorder the layout of `a` and `b` in memory (because this is not a standard-layout class). No compiler has ever actually done that, and IIRC the permission to reorder memory layouts has been proposed-to-be-revoked and maybe even scaled back in C++23.
> It's kind of the same idea, from the 1990s point of view: Instead of forcing the programmer to write everything in the "correct" order like bad old C, let's permit the programmer to write in whatever order they like, and then the compiler can magically fix it up! Hooray C++!
> It's only after like 20 years of that stuff that enough people are publicly saying "well, this is confusing; we should just force the programmer to write what they mean."
>
> –Arthur
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2022-02-25 18:13:13