1  // -*- C++ -*-
       2  // Testing utilities for the rvalue reference.
       3  //
       4  // Copyright (C) 2005-2023 Free Software Foundation, Inc.
       5  //
       6  // This file is part of the GNU ISO C++ Library.  This library is free
       7  // software; you can redistribute it and/or modify it under the
       8  // terms of the GNU General Public License as published by the
       9  // Free Software Foundation; either version 3, or (at your option)
      10  // any later version.
      11  //
      12  // This library is distributed in the hope that it will be useful,
      13  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15  // GNU General Public License for more details.
      16  //
      17  // You should have received a copy of the GNU General Public License along
      18  // with this library; see the file COPYING3.  If not see
      19  // <http://www.gnu.org/licenses/>.
      20  //
      21  
      22  #ifndef _GLIBCXX_TESTSUITE_RVALREF_H
      23  #define _GLIBCXX_TESTSUITE_RVALREF_H 1
      24  
      25  #include <testsuite_hooks.h>
      26  #include <bits/functional_hash.h>
      27  
      28  namespace __gnu_test
      29  {
      30    // This class is designed to test libstdc++'s template-based rvalue
      31    // reference support. It should fail at compile-time if there is an
      32    // attempt to copy it.
      33    struct rvalstruct
      34    {
      35      int val;
      36      bool valid;
      37  
      38      rvalstruct() : val(0), valid(true)
      39      { }
      40  
      41      rvalstruct(int inval) : val(inval), valid(true)
      42      { }
      43  
      44      rvalstruct&
      45      operator=(int newval)
      46      {
      47        val = newval;
      48        valid = true;
      49        return *this;
      50      }
      51  
      52      rvalstruct(const rvalstruct&) = delete;
      53  
      54      rvalstruct(rvalstruct&& in)
      55      {
      56        VERIFY( in.valid == true );
      57        val = in.val;
      58        in.valid = false;
      59        valid = true;
      60      }
      61  
      62      rvalstruct&
      63      operator=(const rvalstruct&) = delete;
      64  
      65      rvalstruct&
      66      operator=(rvalstruct&& in)
      67      {
      68        VERIFY( this != &in );
      69        VERIFY( in.valid == true );
      70        val = in.val;
      71        in.valid = false;
      72        valid = true;
      73        return *this;
      74      }
      75    };
      76  
      77    inline bool
      78    operator==(const rvalstruct& lhs, const rvalstruct& rhs)
      79    { return lhs.val == rhs.val; }
      80  
      81    inline bool
      82    operator<(const rvalstruct& lhs, const rvalstruct& rhs)
      83    { return lhs.val < rhs.val; }
      84  
      85    void
      86    swap(rvalstruct& lhs, rvalstruct& rhs)
      87    {
      88      VERIFY( lhs.valid && rhs.valid );
      89      int temp = lhs.val;
      90      lhs.val = rhs.val;
      91      rhs.val = temp;
      92    }
      93  
      94    // This is a moveable class which copies how many times it is copied.
      95    // This is mainly of use in the containers, where the an element inserted
      96    // into a container has to be copied once to get there, but we want to check
      97    // nothing else is copied.
      98    struct copycounter
      99    {
     100      static int copycount;
     101      int val;
     102      bool valid;
     103  
     104      copycounter() : val(0), valid(true)
     105      { }
     106  
     107      copycounter(int inval) : val(inval), valid(true)
     108      { }
     109  
     110      copycounter(const copycounter& in) : val(in.val), valid(true)
     111      {
     112        VERIFY( in.valid == true );
     113        ++copycount;
     114      }
     115  
     116      copycounter(copycounter&& in) noexcept
     117      {
     118        VERIFY( in.valid == true );
     119        val = in.val;
     120        in.valid = false;
     121        valid = true;
     122      }
     123  
     124      copycounter&
     125      operator=(int newval)
     126      {
     127        val = newval;
     128        valid = true;
     129        return *this;
     130      }
     131  
     132      bool
     133      operator=(const copycounter& in)
     134      {
     135        VERIFY( in.valid == true );
     136        ++copycount;
     137        val = in.val;
     138        valid = true;
     139        return true;
     140      }
     141  
     142      copycounter&
     143      operator=(copycounter&& in)
     144      {
     145        VERIFY(in.valid == true);
     146        val = in.val;
     147        in.valid = false;
     148        valid = true;
     149        return *this;
     150      }
     151  
     152      ~copycounter() noexcept
     153      { valid = false; }
     154    };
     155  
     156    int copycounter::copycount = 0;
     157  
     158    inline bool
     159    operator==(const copycounter& lhs, const copycounter& rhs)
     160    { return lhs.val == rhs.val; }
     161  
     162    inline bool
     163    operator<(const copycounter& lhs, const copycounter& rhs)
     164    { return lhs.val < rhs.val; }
     165  
     166    inline void
     167    swap(copycounter& lhs, copycounter& rhs)
     168    {
     169      VERIFY( lhs.valid && rhs.valid );
     170      int temp = lhs.val;
     171      lhs.val = rhs.val;
     172      rhs.val = temp;
     173    }
     174  
     175    // In the occasion of libstdc++/48038.
     176    struct rvalstruct_compare_by_value
     177    {
     178      int val;
     179      bool ok;
     180  
     181      rvalstruct_compare_by_value(int v)
     182      : val(v), ok(true) { }
     183  
     184      rvalstruct_compare_by_value(const rvalstruct_compare_by_value& rh)
     185      : val(rh.val), ok(rh.ok)
     186      {
     187        VERIFY(rh.ok);
     188      }
     189  
     190      rvalstruct_compare_by_value&
     191      operator=(const rvalstruct_compare_by_value& rh)
     192      {
     193        VERIFY( rh.ok );
     194        val = rh.val;
     195        ok = rh.ok;
     196        return *this;
     197      }
     198  
     199      rvalstruct_compare_by_value(rvalstruct_compare_by_value&& rh)
     200      : val(rh.val), ok(rh.ok)
     201      {
     202        VERIFY( rh.ok );
     203        rh.ok = false;
     204      }
     205  
     206      rvalstruct_compare_by_value&
     207      operator=(rvalstruct_compare_by_value&& rh)
     208      {
     209        VERIFY( rh.ok );
     210        val = rh.val;
     211        ok = rh.ok;
     212        rh.ok = false;
     213        return *this;
     214      }
     215    };
     216  
     217    inline bool
     218    operator<(rvalstruct_compare_by_value lh,
     219  	    rvalstruct_compare_by_value rh)
     220    {
     221      VERIFY( rh.ok );
     222      VERIFY( lh.ok );
     223      return lh.val < rh.val;
     224    }
     225  
     226    inline bool
     227    order(rvalstruct_compare_by_value lh,
     228  	rvalstruct_compare_by_value rh)
     229    {
     230      VERIFY( rh.ok );
     231      VERIFY( lh.ok );
     232      return lh.val < rh.val;
     233    }
     234  
     235    struct throwing_move_constructor
     236    {
     237      throwing_move_constructor() = default;
     238  
     239      throwing_move_constructor(throwing_move_constructor&&)
     240      { throw 1; }
     241  
     242      throwing_move_constructor(const throwing_move_constructor&) = default;
     243  
     244      throwing_move_constructor&
     245      operator=(const throwing_move_constructor&) = default;
     246    };
     247  
     248  } // namespace __gnu_test
     249  
     250  namespace std
     251  {
     252    /// std::hash specialization for __gnu_test::rvalstruct.
     253    template<>
     254      struct hash<__gnu_test::rvalstruct>
     255      {
     256        typedef size_t                    result_type;
     257        typedef __gnu_test::rvalstruct  argument_type;
     258  
     259        size_t
     260        operator()(const __gnu_test::rvalstruct& __rvs) const
     261        { return __rvs.val; }
     262      };
     263  }
     264  
     265  #endif // _GLIBCXX_TESTSUITE_TR1_H