[libcxx-dev] Sequence container swap noexcept specifiers not-to-spec

Christopher Di Bella via libcxx-dev libcxx-dev at lists.llvm.org
Thu Mar 4 09:14:10 PST 2021


On Thu, 4 Mar 2021, 09:03 Tim Song, <t.canens.cpp at gmail.com> wrote:

> On Thu, Mar 4, 2021 at 10:12 AM Louis Dionne via libcxx-dev
> <libcxx-dev at lists.llvm.org> wrote:
> >
> >
> >
> > On Feb 20, 2021, at 14:12, Christopher Di Bella <cjdb.ns at gmail.com>
> wrote:
> >
> > I've noticed that our sequence containers' noexcept specifiers for swap
> aren't to spec. Is this intentional, or some gross oversight?
> >
> > Example from <vector>
> >
> >     void swap(vector&)
> > #if _LIBCPP_STD_VER >= 14
> >         _NOEXCEPT;
> > #else
> >         _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
> >                     __is_nothrow_swappable<allocator_type>::value);
> > #endif
> >
> > To me, this looks like it's saying that swap is unconditionally noexcept
> in C++17 and C++20, and possibly the opposite of [vector.capacity]/12
> otherwise?
> >
> > [vector.capacity]/12 notes:
> >
> > constexpr void swap(vector& x)
> >
>  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
> >            allocator_traits<Allocator>::is_always_equal::value);
> >
> > If this is an oversight, I'll file a bug and patch ASAP. If it's
> intentional, is it explicitly documented somewhere to explain the
> deviation? This was a surprise when writing tests for std::ranges::swap's
> noexcept status.
> >
> >
> > Based on https://en.cppreference.com/w/cpp/container/vector/swap, it
> seems to me like what we want here is:
> >
> >     void swap(vector&)
> >     #if _LIBCPP_STD_VER < 17
> >         _NOEXCEPT
> >     #else
> >
>  _NOEXCEPT_((std::allocator_traits<Allocator>::propagate_on_container_swap::value
> ||
> >
>  std::allocator_traits<Allocator>::is_always_equal::value))
> >     #endif
> >
> > In other words, mark it as unconditionally noexcept (as a conforming
> extension) pre-C++17, and implement the noexcept specification per the spec
> in C++17 and above. Do you agree? If so, I think it would be great to
> submit a patch and add tests for all the places where this is broken. I
> would be verrrrry grateful if you were willing to do that, I’ll review it.
> >
> > Louis
>

Yep, I'll happily do the sequence containers between <concepts> and
<iterator>.

Might need some more time getting an understanding of the (unordered)?
associative containers before I'm comfortable touching them.


> I don't think this is an oversight. The conditional noexcept on swap
> in the standard is entirely due to the Lakos rule (swapping containers
> with non-propagating unequal allocators is undefined), so the
> unconditional noexcept is a permissible strengthening. The
> __is_nothrow_swappable check pre-17 is presumably to support
> allocators with throwing swaps, which were banned by LWG2016.
>
> If a change is desirable, I would suggest treating LWG2016 as a DR and
> using unconditional noexcept across the board.
>

I see LWG2016 is P2 and hasn't been looked at since 2017. What would be
necessary to get LWG to review this again?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/libcxx-dev/attachments/20210304/20a47653/attachment-0001.html>


More information about the libcxx-dev mailing list