C++ Logo

std-discussion

Advanced search

Re: Vector implementation of behavior when inserting objects whose copy constructor can throw

From: Brian Bi <bbi5291_at_[hidden]>
Date: Tue, 27 Jul 2021 15:59:40 -0400
On Tue, Jul 27, 2021 at 3:49 PM Giuseppe D'Angelo via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> Hello,
>
> On 27/07/2021 21:09, Andrey Semashev via Std-Discussion wrote:
> > On 7/27/21 6:29 PM, Jason McKesson via Std-Discussion wrote:
> >> On Sun, Jul 25, 2021 at 3:21 PM Andrey Semashev via Std-Discussion
> >> <std-discussion_at_[hidden]> wrote:
> >>>
> >>> There is always the solution to always reallocate the storage and do
> the
> >>> full copy with the inserted element.
> >>
> >> That isn't allowed. `insert` is required to maintain the validity of
> >> pointers/references to elements before the insertion point *unless*
> >> reallocation occurs.
> >
> > Exactly. The important part is "unless reallocation occurs".
> >
> >> And reallocation is only *permitted* to occur if
> >> the number of new elements inserted exceeds the available capacity -
> >> size.
> >
> > Is it? I don't see where the spec has such restriction for insert. There
> > is one for e.g. reserve, but not for insert.
>
> Are you saying that insert() may reallocate even if you have extra
> capacity? That would be quite an extraordinary behaviour, completely
> user-unfriendly...
>
> >
> >> So you can't implement it that way.
> >>
> >>> Also, there is a possibility of a non-throwing swap, although if move
> is
> >>> throwing then swap will likely be throwing as well.
> >>
> >> I don't see anything in the standard requiring such a thing or
> >> permitting a `vector` implementation to use it. So `vector` still has
> >> to provide this behavior for types with throwing copies that don't
> >> have non-throwing swaps.
> >
> > The standard doesn't specify the exact algorithm of insertion. So the
> > implementation is permitted e.g. to push_back the new element and then
> > move it to its desired position via swaps, if that implementation has
> > benefits. This implementation would satisfy the complexity requirements.
> > Though, as I said, such case is unusual, so it is unlikely any real
> > implementation would bother doing this.
>
> If you have a type that is throwing copyable and movable, I think it's a
> safe bet to assume it's also throwing swappable. Such "append at end and
> swap into position" algorithm would therefore fail to work -- what if an
> exception is thrown while you're swapping?
>

Copy and move constructors always create new objects, whereas the swap
function doesn't. This allows swap to be noexcept in more cases. An example
is libstdc++'s std::deque implementation (assuming standard allocator).

Anyway, I don't think that swapping is actually a valid implementation
strategy. What if swap(T&, T&) has observable effects besides swapping the
two objects? Is std::vector<T>::insert allowed to produce those effects?


>
> My 2 c,
> --
> 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
>
> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>


-- 
*Brian Bi*

Received on 2021-07-27 14:59:55