Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I forward construction in the body of a constructor?

Let's consider that during the execution of the constructor of a class S, it appears that S could be constructed using another constructor. One solution could be to make a placement new at this to reuse the storage:

struct S{
    unsigned int j; //no const neither reference non static members
    S(unsigned int i){/*...*/}
    S(int i){
       if (i>=0) {
         new (this) S(static_cast<unsigned int>(i));
         return;}
       /*...*/
       }
    };
 int i=10;
 S x{i};//is it UB?

Storage reuse is defined in [basic.life]. I don't know how to read this section when the storage is (re)used during constructor execution.

like image 246
Oliv Avatar asked Sep 21 '18 08:09

Oliv


1 Answers

The standard is completely underspecified in this case, and I cannot find a relevant CWG issue.

In itself, your placement new is not UB. After all, you have storage without an object, so you can directly construct an object in it. As you correctly said, the lifetime of the first object hasn't started yet.

But now the problem is: What happens to the original object? Because normally, a constructor is only called on storage without an object and the end of constructor marks the start of the lifetime of the object. But now there is already another object. Is the new object destroyed? Does it have no effect?

The standard is missing a paragraph in [class.cdtor] that says what should happen if a new object is created in the storage of an object under construction and destruction.

You can even construct even weirder code:

struct X {
  X *object;
  int var;
  X() : object(new (this) X(4)), var(5) {} // ?!?
  X(int x) : var(x) {}
} x;
like image 58
Rakete1111 Avatar answered Oct 05 '22 18:10

Rakete1111