[libcxx-dev] std::vector using copy constructor on existing elements during reserve()

Eric Fiselier via libcxx-dev libcxx-dev at lists.llvm.org
Sun Apr 28 18:36:22 PDT 2019


Changing the behavior of unary noexcept  is a much larger and complicated
change than fixing vector.

At the moment `-fno-exceptions` is a subset of standard C++. Changing
noexcept would make it non-standard and non-portable.
Do we want that?

And there's just nastiness like this:

void bar();
void bar() noexcept(noexcept(bar())); // Cool
void bar(); noexcept(false); // Also Cool

We should pursue std::vector separately. I think the current wording allows
either moves or copies, as long as "if an exception is thrown, there are no
effects".
For example [1]

void push_back(const T& x); void push_back(T&& x);
Remarks: [...]
If an exception is thrown other than by the copy constructor, move
constructor, assignment operator, or move assignment operator of T or by
any InputIterator operation there are no effects.
<http://eel.is/c++draft/vector#modifiers-1.sentence-4>

If an exception is thrown while inserting a single element at the end and T
 is Cpp17CopyInsertable or is_­nothrow_­move_­constructible_­v<T> is true,
there are no effects. <http://eel.is/c++draft/vector#modifiers-1.sentence-5>

Otherwise, if an exception is thrown by the move constructor of a non-
Cpp17CopyInsertable T, the effects are unspecified.
<http://eel.is/c++draft/vector#modifiers-1.sentence-6>


Cpp17CopyInsertible implies Cpp17MoveInsertable. And we meet the "if
exception, no effects" requirements trivially.
I might be squinting at the wording too hard, but I think I can fix this as
QoI.

/Eric

[1] http://eel.is/c++draft/container.requirements#general-11
[2] http://eel.is/c++draft/sequences#vector.modifiers

On Wed, Apr 17, 2019 at 7:44 PM Duncan Exon Smith via libcxx-dev <
libcxx-dev at lists.llvm.org> wrote:

>
>
> On 2019 Apr  17, at 11:06, Louis Dionne <ldionne at apple.com> wrote:
>
>
>
> On Apr 17, 2019, at 13:38, JF Bastien <jfbastien at apple.com> wrote:
>
>
>
> On Apr 17, 2019, at 10:12 AM, Louis Dionne via libcxx-dev <
> libcxx-dev at lists.llvm.org> wrote:
>
>
>
> On Apr 17, 2019, at 12:39, Duncan P. N. Exon Smith <dexonsmith at apple.com>
> wrote:
>
> I'm curious about how people feel this should/could behave with
> -fno-exceptions.  IIRC, Libc++ calls the copy constructor (following the
> standard), but -fno-exceptions isn't really standard, and from a user
> perspective that doesn't make sense.  `noexcept` is essentially meaningless
> with -fno-exceptions.
>
>
> I personally feel like it would be surprising if -fno-exceptions caused
> the move constructor to be called instead of the copy constructor. My
> mental model is that -fno-exceptions only disables exceptions as a language
> feature, but doesn't really instruct libraries to provide a different API
> (even though the difference in this case is very small). Instead, I feel
> like it would make more sense if "everything" was implicitly marked
> noexcept when -fno-exceptions is used (because that's really the case). The
> library would behave optimally with -fno-exceptions without having to do
> anything special.
>
>
> IIUC what you’re saying: the library should just use the noexcept operator
> to do its business, and it seem like -fno-exceptions should make noexcept
> always return true? That would be pretty consistent (more than teaching the
> library about -fno-exceptions for move / copy).
>
>
> Yes, that's what I mean. I agree with Eric that moving instead of copying
> provides value, but I think the right way to do it is not to special case
> libc++, but instead to have all code bases become better under
> -fno-exceptions by making noexcept do the right thing.
>
>
> Yeah, that makes sense to me too.
>
> +Richard, I could have sworn you and I chatted quickly about this back in
> 2016 by my mail-search-fu is failing me.  What are your thoughts on having
> -fno-exceptions affect the value of `noexcept`?
>
>
>
> Louis
>
>
> Thoughts?
>
> On Apr 16, 2019, at 23:19, Eric Fiselier via libcxx-dev <
> libcxx-dev at lists.llvm.org> wrote:
>
>
>
> On Tue, Apr 16, 2019 at 2:25 PM Michael Narigon via libcxx-dev <
> libcxx-dev at lists.llvm.org> wrote:
>
>> std:vector is using the element copy constructor on existing elements
>> during its resizing operation in reserve(). I would expect it to use the
>> move constructor for efficiency. Is this intended behavior?
>>
>
> Yes, this behavior is mandated by the standard. The copy constructor is
> used when the move constructor is not noexcept. From cppreference's
> `std::move_if_noexcept` documentation:
>
> std::vector::resize
>> <https://en.cppreference.com/w/cpp/container/vector/resize>, which may
>> have to allocate new storage and then move or copy elements from old
>> storage to new storage.
>> If an exception occurs during this operation, std::vector::resize
>> <https://en.cppreference.com/w/cpp/container/vector/resize> undoes
>> everything it did to this point, which is only possible if
>> std::move_if_noexcept was used to decide whether to use move
>> construction or copy construction. (unless copy constructor is
>
> not available, in which case move constructor is used either way and the
>> strong exception guarantee may be waived)
>
>  https://en.cppreference.com/w/cpp/utility/move_if_noexcept
>
> If you add `noexcept` to your move constructor, vector should call the
> move constructor.
>
>
>
>
>>
>> This is with the libc++ delivered with Xcode 10.1.
>>
>> Attached is a sample program displaying the behavior.
>> _______________________________________________
>> libcxx-dev mailing list
>> libcxx-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>>
> _______________________________________________
> libcxx-dev mailing list
> libcxx-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
>
>
> _______________________________________________
> libcxx-dev mailing list
> libcxx-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
>
> _______________________________________________
> libcxx-dev mailing list
> libcxx-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/libcxx-dev/attachments/20190428/ea7f5ebb/attachment-0001.html>


More information about the libcxx-dev mailing list