<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 4 Mar 2021, 09:03 Tim Song, <<a href="mailto:t.canens.cpp@gmail.com">t.canens.cpp@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Thu, Mar 4, 2021 at 10:12 AM Louis Dionne via libcxx-dev<br>
<<a href="mailto:libcxx-dev@lists.llvm.org" target="_blank" rel="noreferrer">libcxx-dev@lists.llvm.org</a>> wrote:<br>
><br>
><br>
><br>
> On Feb 20, 2021, at 14:12, Christopher Di Bella <<a href="mailto:cjdb.ns@gmail.com" target="_blank" rel="noreferrer">cjdb.ns@gmail.com</a>> wrote:<br>
><br>
> I've noticed that our sequence containers' noexcept specifiers for swap aren't to spec. Is this intentional, or some gross oversight?<br>
><br>
> Example from <vector><br>
><br>
>     void swap(vector&)<br>
> #if _LIBCPP_STD_VER >= 14<br>
>         _NOEXCEPT;<br>
> #else<br>
>         _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||<br>
>                     __is_nothrow_swappable<allocator_type>::value);<br>
> #endif<br>
><br>
> 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?<br>
><br>
> [vector.capacity]/12 notes:<br>
><br>
> constexpr void swap(vector& x)<br>
>   noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||<br>
>            allocator_traits<Allocator>::is_always_equal::value);<br>
><br>
> 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.<br>
><br>
><br>
> Based on <a href="https://en.cppreference.com/w/cpp/container/vector/swap" rel="noreferrer noreferrer" target="_blank">https://en.cppreference.com/w/cpp/container/vector/swap</a>, it seems to me like what we want here is:<br>
><br>
>     void swap(vector&)<br>
>     #if _LIBCPP_STD_VER < 17<br>
>         _NOEXCEPT<br>
>     #else<br>
>         _NOEXCEPT_((std::allocator_traits<Allocator>::propagate_on_container_swap::value ||<br>
>                     std::allocator_traits<Allocator>::is_always_equal::value))<br>
>     #endif<br>
><br>
> 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.<br>
><br>
> Louis<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Yep, I'll happily do the sequence containers between <concepts> and <iterator>.</div><div dir="auto"><br></div><div dir="auto">Might need some more time getting an understanding of the (unordered)? associative containers before I'm comfortable touching them.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I don't think this is an oversight. The conditional noexcept on swap<br>
in the standard is entirely due to the Lakos rule (swapping containers<br>
with non-propagating unequal allocators is undefined), so the<br>
unconditional noexcept is a permissible strengthening. The<br>
__is_nothrow_swappable check pre-17 is presumably to support<br>
allocators with throwing swaps, which were banned by LWG2016.<br>
<br>
If a change is desirable, I would suggest treating LWG2016 as a DR and<br>
using unconditional noexcept across the board.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">I see LWG2016 is P2 and hasn't been looked at since 2017. What would be necessary to get LWG to review this again?</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>