Use if-constexpr instead of overloading for customization point
authorJonathan Wakely <jwakely@redhat.com>
Wed, 30 Oct 2019 17:42:04 +0000 (17:42 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 30 Oct 2019 17:42:04 +0000 (17:42 +0000)
This combines two of the std::ranges::swap.operator() overloads into a
single function template. Using if-constexpr to choose between
implementations should give the compiler less work to do than using
overloading.

* include/std/concepts (std::ranges::swap): Use a single overload for
the non-array cases, and switch using if-constexpr.

From-SVN: r277635

libstdc++-v3/ChangeLog
libstdc++-v3/include/std/concepts

index 864c8aa81eb897152fafe12c8b1140651415983d..059976e9f6f3d1bce428012f74cb2fb062f63c73 100644 (file)
@@ -1,5 +1,8 @@
 2019-10-30  Jonathan Wakely  <jwakely@redhat.com>
 
+       * include/std/concepts (std::ranges::swap): Use a single overload for
+       the non-array cases, and switch using if-constexpr.
+
        * include/bits/stl_iterator.h (__normal_iterator::iterator_concept):
        Guard with __cpp_lib_concepts macro.
 
index 68cbba9b8a7b6bfcdc4c65681c5e38efbb0a1965..c4acfd2e212f1830b4e52a46cd06c4565633adcc 100644 (file)
@@ -173,12 +173,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       struct _Swap
       {
+      private:
+       template<typename _Tp, typename _Up>
+         static constexpr bool
+         _S_noexcept()
+         {
+           if constexpr (__adl_swap<_Tp, _Up>)
+             return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()));
+           else
+             return is_nothrow_move_constructible_v<remove_reference_t<_Tp>>
+                  && is_nothrow_move_assignable_v<remove_reference_t<_Tp>>;
+         }
+
+      public:
        template<typename _Tp, typename _Up>
          requires __adl_swap<_Tp, _Up>
+         || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp>
+             && move_constructible<remove_reference_t<_Tp>>
+             && assignable_from<_Tp, remove_reference_t<_Tp>>)
          constexpr void
          operator()(_Tp&& __t, _Up&& __u) const
-         noexcept(noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())))
-         { swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }
+         noexcept(_S_noexcept<_Tp, _Up>())
+         {
+           if constexpr (__adl_swap<_Tp, _Up>)
+             swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
+           else
+             {
+               auto __tmp = static_cast<remove_reference_t<_Tp>&&>(__t);
+               __t = static_cast<remove_reference_t<_Tp>&&>(__u);
+               __u = static_cast<remove_reference_t<_Tp>&&>(__tmp);
+             }
+         }
 
        template<typename _Tp, typename _Up, size_t _Num>
          requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) {
@@ -191,19 +216,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            for (size_t __n = 0; __n < _Num; ++__n)
              (*this)(__e1[__n], __e2[__n]);
          }
-
-       template<typename _Tp>
-         requires (!__adl_swap<_Tp&, _Tp&>
-           && move_constructible<_Tp> && assignable_from<_Tp&, _Tp>)
-         constexpr void
-         operator()(_Tp& __e1, _Tp& __e2) const
-         noexcept(is_nothrow_move_constructible_v<_Tp>
-                  && is_nothrow_move_assignable_v<_Tp>)
-         {
-           _Tp __tmp = static_cast<_Tp&&>(__e1);
-           __e1 = static_cast<_Tp&&>(__e2);
-           __e2 = static_cast<_Tp&&>(__tmp);
-         }
       };
     } // namespace __cust_swap