C++ Logo


Advanced search

Re: On "transparently replaceable" in std::vector operations

From: Giuseppe D'Angelo <giuseppe.dangelo_at_[hidden]>
Date: Wed, 28 Apr 2021 10:17:23 +0200

On 28/04/21 02:03, Jason McKesson via Std-Discussion wrote:
> Plus, it's a lot less fragile to use an index when that's the behavior
> you want. After all, the pointer/reference validity can only be
> allowed if reallocation doesn't occur. Which is not (yet) a thing you
> can guarantee. It's better to write code that can't accidentally be
> broken.

I'm not saying that I have a perfect-use-caseā„¢ for this. In fact, I
don't (also because right now it'll be illegal), and I agree with you
that it sounds fishy. But let's ignore that for a moment.

I'm just asking, from a consistency point of view, why do such
guarantees exist for a "hand-rolled vector", and not for std::vector
itself? It seems to me that [basic.life] says that this hand-rolled
insert(begin()) is valid:

> X *p = ~~~; // points to storage for C objects of type X; currently only S objects exist in p[0]...p[S-1]; C > S
> // insert launder and other magic as required, assume pointer arithmetic is fine, etc.
> new (p[S]) X(std::move(p[S-1]));
> p[S-1] = std::move(p[S-2]);
> p[S-2] = std::move(p[S-3]);
> // ...
> p[0] = std::move(newX);
> use(*p); // OK; p points to the newly inserted object

Why isn't the totally equivalent operation on `std::vector` valid as well?

Note: an answer such as "this simply wasn't considered when that wording
to [basic.life] was adopted in C++20 (?), LEWG paper please" is
perfectly OK to me. As well as "you're missing this-and-that subclause,
that's why", "implementations are allowed to implement vector with a
prepend optimization", or similar.

Thank you,
Giuseppe D'Angelo | giuseppe.dangelo_at_[hidden] | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts

Received on 2021-04-28 03:17:30