Skip to content

Decomposing relocation constructor #36

Description

@SebastienBini

Now that we have decomposing functions, and that D2839R1 achieves its relocation constructor with authorizing reloc in ctor-initializer, I think we can do better than what we are currently proposing.

What if the relocation constructor could act as a decomposing function with regards to its source object?
Right before entering the ctor-initializer, the source is decomposed into individual objects for each direct base and non-static data member. They live for the duration of the ctor-initializer, and if they are not relocated, they are otherwise destroyed in reversed declaration order.

class T : public B
{
public:
  T(T reloc) : /* starts lifetime of "B", _d1, _d2 and _d3 */
    B{reloc B}, _d1{reloc _d1}, _d2{this->_d1}
    /* _d3 and _d2 are destroyed, in that order */
  {}

private:
  D1 _d1;
  D2 _d2;
  D3 _d3;
};

We could even go as far as allowing delegating constructors with this approach:

class T : public B
{
public:
  T(T src) : T(reloc src, std::lock_guard{some_mutex}) {}

private:
  T(T reloc, std::lock_guard<std::mutex>) : /* starts lifetime of "B", _d1, _d2 and _d3 */
     B{reloc B}, _d1{reloc _d1}, _d2{this->_d1}
    /* _d3 and _d2 are destroyed, in that order */
    {}

private:
  D1 _d1;
  D2 _d2;
  D3 _d3;
};

The relocation constructor as currently proposed can stay. I believe the delegating ctor case is a motivating example of why we need both. This decomposing relocation constructor would only be reserved if the source object is named reloc. This allows us to write a second relocation ctor (like the private ctor of T) which benefits from the decomposition trait.

In the example, we might infinitely call the relocation constructor when building the first parameter of the private constructor. I believe the compiler must now that there exists an elided version of that private ctor so that it needn't call the relocation ctor again until it blows up the stack :/ Hence reloc must appear in the declaration of that second ctor. This should be okay as we cannot take the address of a constructor. However it feels a bit off that the name of a parameter changes the ABI, so maybe we should allow, for relocation constructors only, reloc T as well as T reloc: T(reloc T, std::lock_guard<std::mutex>) : ....

And... what about decomposing relocation assignment operator? I think they should be allowed if decomposing relocation ctors are a thing. I have not much to say about them though, no particular issue comes to mind.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions