https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80794

--- Comment #5 from Martin Sebor <msebor at gcc dot gnu.org> ---
S::i cannot change during the lifetime of an S object because S::i is declared
const.  This holds regardless of whether the S object itself is const.

[basic.life] outlines the restrictions on creating a new object in the storage
occupied by an object whose lifetime has ended and covers Andrew's question
from comment #3:

-8-  If, after the lifetime of an object has ended and before the storage which
the object occupied is reused or released, a new object is created at the
storage location which the original object occupied, a pointer that pointed to
the original object, a reference that referred to the original object, or the
name of the original object will automatically refer to the new object and,
once the lifetime of the new object has started, can be used to manipulate the
new object, if:
...

--  the type of the original object is not const-qualified, and, if a class
type, does not contain any non-static data member whose type is const-qualified
or a reference type, and
--  the original object was a most derived object (1.8) of type T and the new
object is a most derived object of type T (that is, they are not base class
subobjects).

That precludes defining S::foo() like so:

  void S::foo () const {
    this->~S ();
    new (this) S (456);
  }

or like so

  void S::foo () const {
    i.~int ();
    new (&i) const int (456);
  }

and continuing to use the S object at that address referred to by a reference
or pointer to S like bar() does because doing so would violate the first
bullets and could violate the second (if the s in bar(S &s) referred to a
subobject of an object of a derived type).

Reply via email to