This fixes a bug in _S_nothrow_swap(), where I assumed that allocator types are always swappable, but they don't need to be if propagate_on_container_swap is false. Thanks to Ville's new trait it's easy to fix.
For the branches we don't have __is_nothrow_swappable, but could dispatch on the propagation trait so we only test if swapping throws when we're actually going to swap. However, I'm not sure if _S_nothrow_swap() is actually worth keeping, because the standard says that for allocators that propagate on swap, they shall be swappable and swapping them shall not throw exceptions. This means the current code is doubly-wrong, it assumes allocators are always swappable (not required to be true) and then tests whether swapping them will throw (if they're swappable swapping must not throw). So we could remove all uses of _Alloc_traits::_S_nothrow_swap() and make containers' swap() members unconditionally noexcept. The only reason to keep _S_nothrow_swap is if we want to support allocators with throwing swaps as an extension. Thoughts? For now I'm committing this to trunk, tested powerpc64le-linux.
commit e43ff136f29ca61fc6277fbef7505445c948bf55 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jun 17 11:25:13 2015 +0100 * include/ext/alloc_traits.h (__alloc_traits::_S_nothrow_swap()): Use __is_nothrow_swappable. diff --git a/libstdc++-v3/include/ext/alloc_traits.h b/libstdc++-v3/include/ext/alloc_traits.h index 06bc70a..bd0f759 100644 --- a/libstdc++-v3/include/ext/alloc_traits.h +++ b/libstdc++-v3/include/ext/alloc_traits.h @@ -159,9 +159,8 @@ template<typename _Alloc> static constexpr bool _S_nothrow_swap() { - using std::swap; return !_S_propagate_on_swap() - || noexcept(swap(std::declval<_Alloc&>(), std::declval<_Alloc&>())); + || std::__is_nothrow_swappable<_Alloc>::value; } template<typename _Tp>