Hacker News new | ask | show | jobs
by zalyalov 904 days ago

  struct S {
    int A;
    int B = A;
    int C;
  };

  int i = 0;
  S s = {.C = i++, .A = ++i};

What would you expect code like this to do?
4 comments

The only useful solution for C++ would be to let the compiler reorder the initialization in declaration order, e.g. first A, then B, then C.

This would still be a lot better for 99% of real world use cases than requiring the programmer to manually place the items in declaration order.

This would be a big footgun though. That already happens for initialising class members in constructors and it's enough of a footgun that compilers have a warning to tell you if your initialisation order is different to the declaration order.
Doesn't the same footgun apply to function call arguments which are evaluated in an unspecified order?

    f(a++, b++)
That footgun doesn't seem to have very much impact in the real world that I've seen. Largely because people do not write complex expressions like that anymore. Since we already mostly avoid such expressions, we may as well take the benefit for designated initializers.
Yeah that is a footgun too. Enough that Rust defines argument evaluation order.

It is a much smaller footgun though and I don't recall ever being bitten by it. I have definitely been bitten by member initialisation order though multiple times. Generally because of questionable designs where one member is passed as a parameter of another member and it hasn't actually been initialised yet.

Really I think the answer is to initialise in the order that initialisation is written (this is what Rust does) rather than declaration order. But that would be a breaking change so I guess they opted for the conservative choice.

Yes, and there was a strong push to define the order although it ultimately failed.

On the other hand evaluation order of aggregate initializers is well defined (left to right) and there was little appetite to weaken it.

It might still happen in the future of course.

Fail to compile due to forward references in initializers.

The problem is, someone thought this was a good idea, but the act of supporting it ruled out a lot of more-useful future improvements.

Is `int B = A` even legal? Aren't field initializers like that supposed to be compile time constant?
It's allowed since C++11.
I wouldn't write that, and if someone did they'd get to keep all the pieces.