News for hackers. Stuff that matters.
Re:Fun with C++26 reflection: Keyword Arguments by badmintonbaseba on Tuesday February 11, 2025 @06:35AM (#43011649)
You can't easily take the pointer to an other member in a designated initializer. It's still a problem for members that are implicitly initialized by their default member initializer, but that can be sorted out.
Re:Fun with C++26 reflection: Keyword Arguments by drysine on Tuesday February 11, 2025 @08:46AM (#43012657)
I think it is easy enough to be a potential footgun [0]:

  struct A { A(A*);};

  struct B {
    A a1;
    A a2;
  };

  void f()
  {
    B b{.a1 = A(nullptr), .a2 = A(&b.a1) };
  }

[0] https://godbolt.org/z/cGaxzh17T
Re:Fun with C++26 reflection: Keyword Arguments by badmintonbaseba on Tuesday February 11, 2025 @11:39AM (#43014899)
That's a stretch to call it "easy enough", you are explicitly pointing the gun at your foot. That `b.a1` might not be explicitly UB, but that's quite suspect when b's lifetime didn't start yet. Accessing members through `this` in constructors have some special allowance to not make that UB.
Re:Fun with C++26 reflection: Keyword Arguments by drysine on Monday February 17, 2025 @03:21AM (#43076538)
Good point, I should've used direct initialization in this example.

  struct A { 
    int x;
    A(A *a) { if (a) a->x = 42;}
  };

  struct B {
    A a1;
    A a2;
  };

  void f()
  {
    B b{.a1{nullptr}, .a2{&b.a1} };
  }
This code is valid.

Now if I change the struct definition to

  struct B {
    A a2;
    A a1;
  };
it will become UB. Luckily it won't compile because of the difference between the order of declaration and the order of designated initializers.

The alternative way is to always initialize the sub-objects in the order of designated initializers (what do we do if not all initializers are provided?), but this would mean that the order of constructor calls wouldn't match the (reversed) order of destructor calls. Or we would need to select the destructor dynamically based on the way the object was initialized.

https://godbolt.org/z/MPoqEhTvf

Re:Fun with C++26 reflection: Keyword Arguments by badmintonbaseba on Thursday February 20, 2025 @08:44AM (#43114542)
My gripe was not the form of initialization of the elements, but forming `b.a1` before `b`'s lifetime has started. It hasn't started before all of the elements are initialized.
Re:Fun with C++26 reflection: Keyword Arguments by drysine on Thursday February 20, 2025 @02:22PM (#43118943)
But do we need the lifetime of b to be started? Isn't it enough that a1's lifetime is started? Taking of address of a1 happens after that. [0]

Upd:

There is an interesting sentence in [class.cdtor] but I don't think it applies here because B has no constructors:

"For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior."[1]

[0] https://eel.is/c++draft/dcl.init.aggr#7

[1] https://eel.is/c++draft/class.cdtor#1