1  // Copyright (C) 2015-2023 Free Software Foundation, Inc.
       2  //
       3  // This file is part of the GNU ISO C++ Library.  This library is free
       4  // software; you can redistribute it and/or modify it under the
       5  // terms of the GNU General Public License as published by the
       6  // Free Software Foundation; either version 3, or (at your option)
       7  // any later version.
       8  //
       9  // This library is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License along
      15  // with this library; see the file COPYING3.  If not see
      16  // <http://www.gnu.org/licenses/>.
      17  
      18  #include <type_traits>
      19  #include <testsuite_tr1.h>
      20  #include <utility>
      21  #include <array>
      22  #include <tuple>
      23  #include <queue>
      24  #include <stack>
      25  
      26  #if defined(test_std_is_nothrow_swappable)
      27  #  ifndef __cpp_lib_is_swappable
      28  #   error "Feature-test macro for is_nothrow_swappable missing"
      29  #  elif __cpp_lib_is_swappable != 201603
      30  #   error "Feature-test macro for is_nothrow_swappable has wrong value"
      31  #  endif
      32  // Test std::is_nothrow_swappable:
      33  template<class T>
      34  using is_nothrow_swappable = std::is_nothrow_swappable<T>;
      35  #elif defined(test_std_is_nothrow_swappable_ext)
      36  // Test our __is_nothrow_swappable extension:
      37  template<class T>
      38  using is_nothrow_swappable = std::__is_nothrow_swappable<T>;
      39  #else
      40  # error "Either test_std_is_nothrow_swappable or " \
      41          "test_std_is_nothrow_swappable_ext need to be defined"
      42  #endif
      43  
      44  namespace funny {
      45    struct F {};
      46    void swap(F&, F&) = delete;
      47    void swap(F(&)[5], F(&)[5]) noexcept;
      48    void swap(F(&)[6], F(&)[6]);
      49    struct A {};
      50    void swap(A&, A&) noexcept(false);
      51  }
      52  namespace std {
      53    template<>
      54    void swap<funny::A>(funny::A&, funny::A&) noexcept
      55    {
      56    }
      57  
      58    template<>
      59    void swap<funny::A>(funny::A(&)[3], funny::A(&)[3]) noexcept(false)
      60    {
      61    }
      62  }
      63  namespace ns1 {
      64    struct SwapThrow {};
      65    void swap(SwapThrow&, SwapThrow&);
      66    void swap(SwapThrow(&)[3], SwapThrow(&)[3]) noexcept;
      67  }
      68  
      69  namespace ns2 {
      70    struct SwapThrow {
      71      SwapThrow() noexcept = default;
      72      SwapThrow(const SwapThrow&) noexcept(false);
      73      SwapThrow& operator=(const SwapThrow&) noexcept(false);
      74    };
      75  }
      76  
      77  namespace ns3 {
      78    struct SwapNoThrow {
      79      SwapNoThrow() noexcept = default;
      80      SwapNoThrow(const SwapNoThrow&) noexcept(false);
      81      SwapNoThrow& operator =(const SwapNoThrow&) noexcept(false);
      82    };
      83    void swap(SwapNoThrow&, SwapNoThrow&) noexcept;
      84  }
      85  
      86  namespace ns4 {
      87    struct SwapNoThrow {};
      88  }
      89  
      90  namespace ns5 {
      91    struct SwapThrow {
      92      SwapThrow() noexcept = default;
      93      SwapThrow(SwapThrow&&) noexcept;
      94      SwapThrow& operator=(const SwapThrow&) noexcept(false);
      95    };
      96  }
      97  
      98  namespace comps {
      99    struct CompareNoThrowCopyable
     100    {
     101      template<class T>
     102      bool operator()(const T&, const T&) const
     103      { return false; }
     104    };
     105  
     106    struct CompareNonCopyable
     107    {
     108      CompareNonCopyable() = default;
     109      CompareNonCopyable(const CompareNonCopyable&) = delete;
     110      CompareNonCopyable& operator=(const CompareNonCopyable&) noexcept;
     111  
     112      template<class T>
     113      bool operator()(const T&, const T&) const
     114      { return false; }
     115    };
     116  
     117    struct CompareThrowCopyable
     118    {
     119      CompareThrowCopyable() = default;
     120      CompareThrowCopyable(const CompareThrowCopyable&) noexcept(false);
     121      CompareThrowCopyable& operator=(const CompareThrowCopyable&);
     122  
     123      template<class T>
     124      bool operator()(const T&, const T&) const
     125      { return false; }
     126    };
     127  }
     128  
     129  void test01()
     130  {
     131    using namespace __gnu_test;
     132    // Positive tests.
     133    static_assert(test_property<is_nothrow_swappable, int>(true), "");
     134    static_assert(test_property<is_nothrow_swappable, bool>(true), "");
     135    static_assert(test_property<is_nothrow_swappable,
     136      decltype(nullptr)>(true), "");
     137    static_assert(test_property<is_nothrow_swappable, int&>(true), "");
     138    static_assert(test_property<is_nothrow_swappable, int&&>(true), "");
     139    static_assert(test_property<is_nothrow_swappable, int[1]>(true), "");
     140    static_assert(test_property<is_nothrow_swappable, int[1][2]>(true), "");
     141    static_assert(test_property<is_nothrow_swappable, int[1][2][3]>(true), "");
     142    static_assert(test_property<is_nothrow_swappable, funny::F[5]>(true), "");
     143    static_assert(test_property<is_nothrow_swappable, EnumType>(true), "");
     144    static_assert(test_property<is_nothrow_swappable, PODType>(true), "");
     145    static_assert(test_property<is_nothrow_swappable, UnionType>(true), "");
     146    static_assert(test_property<is_nothrow_swappable,
     147      construct::SE>(true), "");
     148    static_assert(test_property<is_nothrow_swappable,
     149      construct::Empty>(true), "");
     150    static_assert(test_property<is_nothrow_swappable, void*>(true), "");
     151    static_assert(test_property<is_nothrow_swappable, void(*)()>(true), "");
     152    static_assert(test_property<is_nothrow_swappable, int const*>(true), "");
     153    static_assert(test_property<is_nothrow_swappable, ClassType*>(true), "");
     154    static_assert(test_property<is_nothrow_swappable,
     155      int ClassType::*>(true), "");
     156    static_assert(test_property<is_nothrow_swappable,
     157      void (ClassType::*)()>(true), "");
     158    static_assert(test_property<is_nothrow_swappable,
     159      int (ClassType::*)() const volatile>(true), "");
     160    static_assert(test_property<is_nothrow_swappable,
     161      ns1::SwapThrow[3]>(true), "");
     162    static_assert(!noexcept(std::swap(std::declval<ns1::SwapThrow(&)[3]>(),
     163                                      std::declval<ns1::SwapThrow(&)[3]>())),
     164                                      "");
     165    static_assert(test_property<is_nothrow_swappable,
     166          ns3::SwapNoThrow>(true), "");
     167    static_assert(!noexcept(std::swap(std::declval<ns3::SwapNoThrow&>(),
     168                                      std::declval<ns3::SwapNoThrow&>())), "");
     169    static_assert(test_property<is_nothrow_swappable,
     170          ns3::SwapNoThrow[1]>(true), "");
     171    static_assert(test_property<is_nothrow_swappable,
     172          ns3::SwapNoThrow[3]>(true), "");
     173    static_assert(test_property<is_nothrow_swappable,
     174          ns3::SwapNoThrow[2][3][4]>(true), "");
     175    static_assert(test_property<is_nothrow_swappable,
     176          ns4::SwapNoThrow>(true), "");
     177    static_assert(test_property<is_nothrow_swappable,
     178          ns4::SwapNoThrow[1]>(true), "");
     179    static_assert(test_property<is_nothrow_swappable,
     180          ns4::SwapNoThrow[3]>(true), "");
     181    static_assert(test_property<is_nothrow_swappable,
     182          ns4::SwapNoThrow[2][3][4]>(true), "");
     183    static_assert(test_property<is_nothrow_swappable,
     184          std::pair<int, int>>(true), "");
     185    static_assert(test_property<is_nothrow_swappable,
     186          std::pair<int, int>[1]>(true), "");
     187    static_assert(test_property<is_nothrow_swappable,
     188          std::pair<int, int>[1][2]>(true), "");
     189    static_assert(test_property<is_nothrow_swappable,
     190          std::tuple<int>>(true), "");
     191    static_assert(test_property<is_nothrow_swappable,
     192          std::tuple<int>[1]>(true), "");
     193    static_assert(test_property<is_nothrow_swappable,
     194          std::tuple<int>[1][2]>(true), "");
     195    static_assert(test_property<is_nothrow_swappable,
     196          std::tuple<>>(true), "");
     197    static_assert(test_property<is_nothrow_swappable,
     198          std::tuple<>[1]>(true), "");
     199    static_assert(test_property<is_nothrow_swappable,
     200          std::tuple<>[1][2]>(true), "");
     201    static_assert(test_property<is_nothrow_swappable,
     202          std::array<int, 1>>(true), "");
     203    static_assert(test_property<is_nothrow_swappable,
     204          std::array<int, 0>>(true), "");
     205    static_assert(test_property<is_nothrow_swappable,
     206          std::array<construct::DelCopy, 0>>(true), "");
     207    static_assert(test_property<is_nothrow_swappable,
     208          std::array<ns1::SwapThrow, 0>>(true), "");
     209    static_assert(test_property<is_nothrow_swappable,
     210          std::queue<int>>(true), "");
     211    static_assert(test_property<is_nothrow_swappable,
     212          std::priority_queue<int>>(true), "");
     213    static_assert(test_property<is_nothrow_swappable,
     214          std::stack<int>>(true), "");
     215    static_assert(test_property<is_nothrow_swappable,
     216          std::priority_queue<int, std::vector<int>,
     217          comps::CompareNoThrowCopyable>>(true), "");
     218  
     219    // Negative tests.
     220    static_assert(test_property<is_nothrow_swappable, void>(false), "");
     221    static_assert(test_property<is_nothrow_swappable, const void>(false), "");
     222    static_assert(test_property<is_nothrow_swappable, void()>(false), "");
     223    static_assert(test_property<is_nothrow_swappable,
     224      void() const>(false), "");
     225    static_assert(test_property<is_nothrow_swappable,
     226      void() volatile>(false), "");
     227    static_assert(test_property<is_nothrow_swappable,
     228      void() const volatile>(false), "");
     229    static_assert(test_property<is_nothrow_swappable, const int>(false), "");
     230    static_assert(test_property<is_nothrow_swappable, const bool>(false), "");
     231    static_assert(test_property<is_nothrow_swappable,
     232      const int[1]>(false), "");
     233    static_assert(test_property<is_nothrow_swappable,
     234      const int[1][2]>(false), "");
     235    static_assert(test_property<is_nothrow_swappable,
     236      const int[1][2][3]>(false), "");
     237    static_assert(test_property<is_nothrow_swappable, int[]>(false), "");
     238    static_assert(test_property<is_nothrow_swappable, const int[]>(false), "");
     239    static_assert(test_property<is_nothrow_swappable, int[][1]>(false), "");
     240    static_assert(test_property<is_nothrow_swappable,
     241      const funny::F[5]>(false), "");
     242    static_assert(test_property<is_nothrow_swappable,
     243      construct::Abstract>(false), "");
     244    static_assert(test_property<is_nothrow_swappable,
     245      construct::DelCopy>(false), "");
     246    static_assert(test_property<is_nothrow_swappable, funny::F>(false), "");
     247    static_assert(test_property<is_nothrow_swappable, funny::F[1]>(false), "");
     248    static_assert(test_property<is_nothrow_swappable,
     249      funny::F[1][2]>(false), "");
     250    static_assert(test_property<is_nothrow_swappable,
     251      funny::F[1][2][3]>(false), "");
     252    static_assert(test_property<is_nothrow_swappable, funny::F[6]>(false), "");
     253    static_assert(test_property<is_nothrow_swappable, funny::A>(false), "");
     254    static_assert(noexcept(std::swap(std::declval<funny::A&>(),
     255                                     std::declval<funny::A&>())), "");
     256    static_assert(test_property<is_nothrow_swappable, funny::A[3]>(false), "");
     257    static_assert(test_property<is_nothrow_swappable,
     258      ns1::SwapThrow>(false), "");
     259    static_assert(test_property<is_nothrow_swappable,
     260      ns1::SwapThrow[1]>(false), "");
     261    static_assert(test_property<is_nothrow_swappable,
     262      ns1::SwapThrow[3][2]>(false), "");
     263    static_assert(test_property<is_nothrow_swappable,
     264      ns1::SwapThrow[2][3][4]>(false), "");
     265    static_assert(test_property<is_nothrow_swappable,
     266      ns2::SwapThrow>(false), "");
     267    static_assert(test_property<is_nothrow_swappable,
     268      ns2::SwapThrow[1]>(false), "");
     269    static_assert(test_property<is_nothrow_swappable,
     270      ns2::SwapThrow[2][3][4]>(false), "");
     271    static_assert(test_property<is_nothrow_swappable,
     272      ns5::SwapThrow>(false), "");
     273    static_assert(test_property<is_nothrow_swappable,
     274      ns5::SwapThrow[1]>(false), "");
     275    static_assert(test_property<is_nothrow_swappable,
     276      ns5::SwapThrow[2][3][4]>(false), "");
     277    static_assert(test_property<is_nothrow_swappable,
     278  		ThrowCopyConsClass>(false), "");
     279    static_assert(test_property<is_nothrow_swappable,
     280  		std::pair<ThrowCopyConsClass, ThrowCopyConsClass>>(false), "");
     281    static_assert(test_property<is_nothrow_swappable,
     282  		std::tuple<ThrowCopyConsClass>>(false), "");
     283    static_assert(test_property<is_nothrow_swappable,
     284  		std::array<ThrowCopyConsClass, 1>>(false), "");
     285    static_assert(test_property<is_nothrow_swappable,
     286  		std::queue<ThrowCopyConsClass>>(true), "");
     287    static_assert(test_property<is_nothrow_swappable,
     288  		std::priority_queue<ThrowCopyConsClass,
     289  				    std::vector<ThrowCopyConsClass>,
     290  				    comps::CompareNoThrowCopyable>>(true), "");
     291    static_assert(test_property<is_nothrow_swappable,
     292  		std::stack<ThrowCopyConsClass>>(true), "");
     293    static_assert(test_property<is_nothrow_swappable,
     294          std::priority_queue<int, std::vector<int>,
     295          comps::CompareNonCopyable>>(false), "");
     296    static_assert(test_property<is_nothrow_swappable,
     297          std::priority_queue<int, std::vector<int>,
     298          comps::CompareThrowCopyable>>(false), "");
     299  }