[PATCH] Use _GLIBCXX_NOEXCEPT_IF for std::swap

Jonathan Wakely jwakely@redhat.com
Thu May 2 19:12:00 GMT 2019


On 02/05/19 20:09 +0100, Jonathan Wakely wrote:
>On 02/05/19 20:34 +0200, Stephan Bergmann wrote:
>>On 29/04/2019 15:26, Jonathan Wakely wrote:
>>>    * include/bits/move.h (swap(T&, T&), swap(T (&)[N], T (&)[N])): Use
>>>    _GLIBCXX_NOEXCEPT_IF to simplify declarations.
>>>
>>>This just avoids having to repeat the name and parameter-list of the
>>>functions.
>>
>>libstdc++-v3/include/std/type_traits still has
>>
>>> template<typename _Tp>
>>>   inline
>>>   typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
>>>			      is_move_constructible<_Tp>,
>>>			      is_move_assignable<_Tp>>::value>::type
>>>   swap(_Tp&, _Tp&)
>>>   noexcept(__and_<is_nothrow_move_constructible<_Tp>,
>>>	            is_nothrow_move_assignable<_Tp>>::value);
>>
>>using noexcept instead of _GLIBCXX_NOEXPECT_IF, and at least during 
>>configure of building LibreOffice with Clang, that causes failure
>>
>>>.../gcc/trunk/lib/gcc/x86_64-pc-linux-gnu/10.0.0/../../../../include/c++/10.0.0/bits/move.h:185:5: error: exception specification in declaration does not match previous declaration
>>>   swap(_Tp& __a, _Tp& __b)
>>>   ^
>>>.../gcc/trunk/lib/gcc/x86_64-pc-linux-gnu/10.0.0/../../../../include/c++/10.0.0/type_traits:2531:5: note: previous declaration is here
>>>   swap(_Tp&, _Tp&)
>>>   ^
>>
>>I didn't try to track down under what conditions 
>>_GLIBCXX_NOEXCEPT_IF would not expand to noexcept, but I assume that 
>>just type_traits needs adapting, too?
>
>That's weird. _GLIBCXX_NOEXCEPT_IF is only empty for C++11, in which
>case the declaration in <type_traits> isn't seen anyway. And there's
>no point using _GLIBCXX_NOEXCEPT_IF in <type_traits> because we can
>(and should) just use noexcept directly in C++11 code. The macro
>exists for code that needs to be compiled as C++98 too.
>
>The only difference is that there's an extra set of parentheses around
>the NOEXCEPT_IF condition, so the preprocessor doesn't try to eat the
>comma.
>
>So one declaration is:
>
> template<typename _Tp>
>   inline
>   typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
>			      is_move_constructible<_Tp>,
>			      is_move_assignable<_Tp>>::value>::type
>   swap(_Tp&, _Tp&)
>   noexcept(__and_<is_nothrow_move_constructible<_Tp>,
>	            is_nothrow_move_assignable<_Tp>>::value);
>
>And the other is:
>
> template<typename _Tp>
>   inline
>   typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
>			      is_move_constructible<_Tp>,
>			      is_move_assignable<_Tp>>::value>::type
>   swap(_Tp&, _Tp&)
>   noexcept((__and_<is_nothrow_move_constructible<_Tp>,
>	            is_nothrow_move_assignable<_Tp>>::value));

Yep, Clang doesn't like that:
https://wandbox.org/permlink/clslE9PGCVtKPppz


>Does adding the extra parens into type_traits fix it? i.e.
>
>--- a/libstdc++-v3/include/std/type_traits
>+++ b/libstdc++-v3/include/std/type_traits
>@@ -2529,8 +2529,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>                             is_move_constructible<_Tp>,
>                             is_move_assignable<_Tp>>::value>::type
>    swap(_Tp&, _Tp&)
>-    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
>-                   is_nothrow_move_assignable<_Tp>>::value);
>+    noexcept((__and_<is_nothrow_move_constructible<_Tp>,
>+                   is_nothrow_move_assignable<_Tp>>::value));
>
>  template<typename _Tp, size_t _Nm>
>    inline
>
>
>



More information about the Libstdc++ mailing list