mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1577 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1577 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
// -*- C++ -*-
 | 
						|
 | 
						|
// Copyright (C) 2009-2016 Free Software Foundation, Inc.
 | 
						|
//
 | 
						|
// This file is part of the GNU ISO C++ Library.  This library is free
 | 
						|
// software; you can redistribute it and/or modify it under the terms
 | 
						|
// of the GNU General Public License as published by the Free Software
 | 
						|
// Foundation; either version 3, or (at your option) any later
 | 
						|
// version.
 | 
						|
 | 
						|
// This library is distributed in the hope that it will be useful, but
 | 
						|
// WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
// General Public License for more details.
 | 
						|
 | 
						|
// You should have received a copy of the GNU General Public License along
 | 
						|
// with this library; see the file COPYING3.  If not see
 | 
						|
// <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
#ifndef _GLIBCXX_EXCEPTION_SAFETY_H
 | 
						|
#define _GLIBCXX_EXCEPTION_SAFETY_H
 | 
						|
 | 
						|
#include <testsuite_container_traits.h>
 | 
						|
#include <ext/throw_allocator.h>
 | 
						|
 | 
						|
// Container requirement testing.
 | 
						|
namespace __gnu_test
 | 
						|
{
 | 
						|
  // Base class for exception testing, contains utilities.
 | 
						|
  struct setup_base
 | 
						|
  {
 | 
						|
    typedef std::size_t 				size_type;
 | 
						|
    typedef std::uniform_int_distribution<size_type> 	distribution_type;
 | 
						|
    typedef std::mt19937 				engine_type;
 | 
						|
 | 
						|
    // Return randomly generated integer on range [0, __max_size].
 | 
						|
    static size_type
 | 
						|
    generate(size_type __max_size)
 | 
						|
    {
 | 
						|
      // Make the generator static...
 | 
						|
      const engine_type engine;
 | 
						|
      const distribution_type distribution;
 | 
						|
      static auto generator = std::bind(distribution, engine,
 | 
						|
					std::placeholders::_1);
 | 
						|
 | 
						|
      // ... but set the range for this particular invocation here.
 | 
						|
      const typename distribution_type::param_type p(0, __max_size);
 | 
						|
      size_type random = generator(p);
 | 
						|
      if (random < distribution.min() || random > distribution.max())
 | 
						|
	std::__throw_out_of_range_fmt(__N("setup_base::generate\n"
 | 
						|
					  "random number generated is: %zu "
 | 
						|
					  "out of range [%zu, %zu]\n"),
 | 
						|
				      (size_t)random,
 | 
						|
				      (size_t)distribution.min(),
 | 
						|
				      (size_t)distribution.max());
 | 
						|
      return random;
 | 
						|
    }
 | 
						|
 | 
						|
    // Given an instantiating type, return a unique value.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct generate_unique
 | 
						|
      {
 | 
						|
	typedef _Tp value_type;
 | 
						|
 | 
						|
	operator value_type()
 | 
						|
	{
 | 
						|
	  static value_type __ret;
 | 
						|
	  ++__ret;
 | 
						|
	  return __ret;
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Partial specialization for pair.
 | 
						|
    template<typename _Tp1, typename _Tp2>
 | 
						|
      struct generate_unique<std::pair<const _Tp1, _Tp2>>
 | 
						|
      {
 | 
						|
	typedef _Tp1 first_type;
 | 
						|
	typedef _Tp2 second_type;
 | 
						|
	typedef std::pair<const _Tp1, _Tp2> pair_type;
 | 
						|
 | 
						|
	operator pair_type()
 | 
						|
	{
 | 
						|
	  static first_type _S_1;
 | 
						|
	  static second_type _S_2;
 | 
						|
	  ++_S_1;
 | 
						|
	  ++_S_2;
 | 
						|
	  return pair_type(_S_1, _S_2);
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Partial specialization for throw_value
 | 
						|
    template<typename _Cond>
 | 
						|
      struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
 | 
						|
      {
 | 
						|
	typedef __gnu_cxx::throw_value_base<_Cond> value_type;
 | 
						|
 | 
						|
	operator value_type()
 | 
						|
	{
 | 
						|
	  static size_t _S_i(0);
 | 
						|
	  return value_type(_S_i++);
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    // Construct container of size n directly. _Tp == container type.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct make_container_base
 | 
						|
      {
 | 
						|
	_Tp _M_container;
 | 
						|
 | 
						|
	make_container_base() = default;
 | 
						|
	make_container_base(const size_type n): _M_container(n) { }
 | 
						|
 | 
						|
	operator _Tp&() { return _M_container; }
 | 
						|
      };
 | 
						|
 | 
						|
    // Construct container of size n, via multiple insertions. For
 | 
						|
    // associated and unordered types, unique value_type elements are
 | 
						|
    // necessary.
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
 | 
						|
      struct make_insert_container_base
 | 
						|
      : public make_container_base<_Tp>
 | 
						|
      {
 | 
						|
	using make_container_base<_Tp>::_M_container;
 | 
						|
	typedef typename _Tp::value_type value_type;
 | 
						|
 | 
						|
	make_insert_container_base(const size_type n)
 | 
						|
	{
 | 
						|
	  for (size_type i = 0; i < n; ++i)
 | 
						|
	    {
 | 
						|
	      value_type v = generate_unique<value_type>();
 | 
						|
	      _M_container.insert(v);
 | 
						|
	    }
 | 
						|
	  assert(_M_container.size() == n);
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct make_insert_container_base<_Tp, false>
 | 
						|
      : public make_container_base<_Tp>
 | 
						|
      {
 | 
						|
	using make_container_base<_Tp>::_M_container;
 | 
						|
	typedef typename _Tp::value_type value_type;
 | 
						|
 | 
						|
	make_insert_container_base(const size_type n)
 | 
						|
	{
 | 
						|
	  for (size_type i = 0; i < n; ++i)
 | 
						|
	    {
 | 
						|
	      value_type v = generate_unique<value_type>();
 | 
						|
	      _M_container.insert(_M_container.end(), v);
 | 
						|
	    }
 | 
						|
	  assert(_M_container.size() == n);
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
 | 
						|
      struct make_container_n;
 | 
						|
 | 
						|
    // Specialization for non-associative types that have a constructor with
 | 
						|
    // a size argument.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct make_container_n<_Tp, true>
 | 
						|
      : public make_container_base<_Tp>
 | 
						|
      {
 | 
						|
	make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct make_container_n<_Tp, false>
 | 
						|
      : public make_insert_container_base<_Tp>
 | 
						|
      {
 | 
						|
	make_container_n(const size_type n)
 | 
						|
	: make_insert_container_base<_Tp>(n) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    // Randomly size and populate a given container reference.
 | 
						|
    // NB: Responsibility for turning off exceptions lies with caller.
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value>
 | 
						|
      struct populate
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::allocator_type	allocator_type;
 | 
						|
	typedef typename container_type::value_type    	value_type;
 | 
						|
 | 
						|
	populate(_Tp& __container)
 | 
						|
	{
 | 
						|
	  const allocator_type a = __container.get_allocator();
 | 
						|
 | 
						|
	  // Size test container.
 | 
						|
	  const size_type max_elements = 100;
 | 
						|
	  size_type n = generate(max_elements);
 | 
						|
 | 
						|
	  // Construct new container.
 | 
						|
	  make_container_n<container_type> made(n);
 | 
						|
	  container_type& tmp = made;
 | 
						|
	  std::swap(tmp, __container);
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Partial specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct populate<_Tp, false>
 | 
						|
      {
 | 
						|
	populate(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
    // Compare two containers for equivalence.
 | 
						|
    // Right now, that means size.
 | 
						|
    // Returns true if equal, throws if not.
 | 
						|
    template<typename _Tp>
 | 
						|
      static bool
 | 
						|
      compare(const _Tp& __control, const _Tp& __test)
 | 
						|
      {
 | 
						|
	// Make sure test container is in a consistent state, as
 | 
						|
	// compared to the control container.
 | 
						|
	// NB: Should be equivalent to __test != __control, but
 | 
						|
	// computed without equivalence operators
 | 
						|
	const size_type szt
 | 
						|
	  = std::distance(__test.begin(), __test.end());
 | 
						|
	const size_type szc
 | 
						|
	  = std::distance(__control.begin(), __control.end());
 | 
						|
 | 
						|
	if (szt != szc)
 | 
						|
	  throw std::logic_error(
 | 
						|
		"setup_base::compare containers size not equal");
 | 
						|
 | 
						|
	// Should test iterator validity before and after exception.
 | 
						|
	bool __equal_it = std::equal(__test.begin(), __test.end(),
 | 
						|
				     __control.begin());
 | 
						|
 | 
						|
	if (!__equal_it)
 | 
						|
	  throw std::logic_error(
 | 
						|
		"setup_base::compare containers iterators not equal");
 | 
						|
 | 
						|
	return true;
 | 
						|
      }
 | 
						|
  };
 | 
						|
 | 
						|
 | 
						|
  // Containing structure holding functors.
 | 
						|
  struct functor_base : public setup_base
 | 
						|
  {
 | 
						|
    // Abstract the erase function.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_base
 | 
						|
      {
 | 
						|
	typedef typename _Tp::iterator 			iterator;
 | 
						|
	typedef typename _Tp::const_iterator		const_iterator;
 | 
						|
 | 
						|
	iterator (_Tp::* _F_erase_point)(const_iterator);
 | 
						|
	iterator (_Tp::* _F_erase_range)(const_iterator, const_iterator);
 | 
						|
 | 
						|
	erase_base()
 | 
						|
	: _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
 | 
						|
      };
 | 
						|
 | 
						|
#if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
 | 
						|
    // Specialization, old C++03 signature.
 | 
						|
    template<typename _Tp1, typename _Tp2, typename _Tp3>
 | 
						|
      struct erase_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
 | 
						|
      {
 | 
						|
	typedef std::basic_string<_Tp1, _Tp2, _Tp3>     container_type;
 | 
						|
	typedef typename container_type::iterator 	iterator;
 | 
						|
 | 
						|
	iterator (container_type::* _F_erase_point)(iterator);
 | 
						|
	iterator (container_type::* _F_erase_range)(iterator, iterator);
 | 
						|
 | 
						|
	erase_base()
 | 
						|
	: _F_erase_point(&container_type::erase),
 | 
						|
	  _F_erase_range(&container_type::erase) { }
 | 
						|
      };
 | 
						|
#endif
 | 
						|
 | 
						|
    // Specialization, as forward_list has erase_after.
 | 
						|
    template<typename _Tp1, typename _Tp2>
 | 
						|
      struct erase_base<std::forward_list<_Tp1, _Tp2>>
 | 
						|
      {
 | 
						|
	typedef std::forward_list<_Tp1, _Tp2> 		container_type;
 | 
						|
	typedef typename container_type::iterator 	iterator;
 | 
						|
	typedef typename container_type::const_iterator const_iterator;
 | 
						|
 | 
						|
	iterator (container_type::* _F_erase_point)(const_iterator);
 | 
						|
	iterator (container_type::* _F_erase_range)(const_iterator,
 | 
						|
						    const_iterator);
 | 
						|
 | 
						|
	erase_base()
 | 
						|
	: _F_erase_point(&container_type::erase_after),
 | 
						|
	  _F_erase_range(&container_type::erase_after) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp,
 | 
						|
	     bool = traits<_Tp>::has_erase::value,
 | 
						|
	     bool = traits<_Tp>::has_erase_after::value>
 | 
						|
      struct erase_point;
 | 
						|
 | 
						|
    // Specialization for most containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_point<_Tp, true, false> : public erase_base<_Tp>
 | 
						|
      {
 | 
						|
	using erase_base<_Tp>::_F_erase_point;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      // NB: Should be equivalent to size() member function, but
 | 
						|
	      // computed with begin() and end().
 | 
						|
	      const size_type sz = std::distance(__container.begin(),
 | 
						|
						 __container.end());
 | 
						|
 | 
						|
	      // NB: Lowest common denominator: use forward iterator operations.
 | 
						|
	      auto i = __container.begin();
 | 
						|
	      std::advance(i, generate(sz));
 | 
						|
 | 
						|
	      // Makes it easier to think of this as __container.erase(i)
 | 
						|
	      (__container.*_F_erase_point)(i);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization for forward_list.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_point<_Tp, false, true> : public erase_base<_Tp>
 | 
						|
      {
 | 
						|
	using erase_base<_Tp>::_F_erase_point;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      // NB: Should be equivalent to size() member function, but
 | 
						|
	      // computed with begin() and end().
 | 
						|
	      const size_type sz = std::distance(__container.begin(),
 | 
						|
						 __container.end());
 | 
						|
 | 
						|
	      // NB: Lowest common denominator: use forward iterator operations.
 | 
						|
	      auto i = __container.before_begin();
 | 
						|
	      std::advance(i, generate(sz));
 | 
						|
 | 
						|
	      // Makes it easier to think of this as __container.erase(i)
 | 
						|
	      (__container.*_F_erase_point)(i);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_point<_Tp, false, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp,
 | 
						|
	     bool = traits<_Tp>::has_erase::value,
 | 
						|
	     bool = traits<_Tp>::has_erase_after::value>
 | 
						|
      struct erase_range;
 | 
						|
 | 
						|
    // Specialization for most containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_range<_Tp, true, false> : public erase_base<_Tp>
 | 
						|
      {
 | 
						|
	using erase_base<_Tp>::_F_erase_range;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const size_type sz = std::distance(__container.begin(),
 | 
						|
						 __container.end());
 | 
						|
	      size_type s1 = generate(sz);
 | 
						|
	      size_type s2 = generate(sz);
 | 
						|
	      auto i1 = __container.begin();
 | 
						|
	      auto i2 = __container.begin();
 | 
						|
	      std::advance(i1, std::min(s1, s2));
 | 
						|
	      std::advance(i2, std::max(s1, s2));
 | 
						|
 | 
						|
	      // Makes it easier to think of this as __container.erase(i1, i2).
 | 
						|
	      (__container.*_F_erase_range)(i1, i2);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization for forward_list.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_range<_Tp, false, true> : public erase_base<_Tp>
 | 
						|
      {
 | 
						|
	using erase_base<_Tp>::_F_erase_range;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const size_type sz = std::distance(__container.begin(),
 | 
						|
						 __container.end());
 | 
						|
	      size_type s1 = generate(sz);
 | 
						|
	      size_type s2 = generate(sz);
 | 
						|
	      auto i1 = __container.before_begin();
 | 
						|
	      auto i2 = __container.before_begin();
 | 
						|
	      std::advance(i1, std::min(s1, s2));
 | 
						|
	      std::advance(i2, std::max(s1, s2));
 | 
						|
 | 
						|
	      // Makes it easier to think of this as __container.erase(i1, i2).
 | 
						|
	      (__container.*_F_erase_range)(i1, i2);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct erase_range<_Tp, false, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
 | 
						|
      struct pop_front
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      __container.pop_front();
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct pop_front<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
 | 
						|
				  && traits<_Tp>::is_reversible::value>
 | 
						|
      struct pop_back
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      __container.pop_back();
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct pop_back<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
 | 
						|
      struct push_front
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::value_type    	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.push_front(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.push_front(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
    };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct push_front<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
 | 
						|
				  && traits<_Tp>::is_reversible::value>
 | 
						|
      struct push_back
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::value_type    	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.push_back(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.push_back(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
    };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct push_back<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
 | 
						|
				  && traits<_Tp>::has_emplace::value>
 | 
						|
      struct emplace_front
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::value_type    	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.emplace_front(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.emplace_front(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
    };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace_front<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
 | 
						|
				  && traits<_Tp>::has_emplace::value
 | 
						|
				  && traits<_Tp>::is_reversible::value>
 | 
						|
      struct emplace_back
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::value_type    	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.emplace_back(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.push_back(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
    };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace_back<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    // Abstract the insert function into two parts:
 | 
						|
    // 1, insert_base_functions == holds function pointer
 | 
						|
    // 2, insert_base == links function pointer to class insert method
 | 
						|
    template<typename _Tp>
 | 
						|
      struct insert_base
 | 
						|
      {
 | 
						|
	typedef typename _Tp::iterator 			iterator;
 | 
						|
	typedef typename _Tp::const_iterator    	const_iterator;
 | 
						|
	typedef typename _Tp::value_type 		value_type;
 | 
						|
 | 
						|
	iterator (_Tp::* _F_insert_point)(const_iterator, const value_type&);
 | 
						|
 | 
						|
	insert_base() : _F_insert_point(&_Tp::insert) { }
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, old C++03 signature.
 | 
						|
    template<typename _Tp1, typename _Tp2, typename _Tp3>
 | 
						|
      struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
 | 
						|
      {
 | 
						|
	typedef std::basic_string<_Tp1, _Tp2, _Tp3> 	container_type;
 | 
						|
	typedef typename container_type::iterator 	iterator;
 | 
						|
	typedef typename container_type::const_iterator	const_iterator;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
 | 
						|
#if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
 | 
						|
	iterator (container_type::* _F_insert_point)(iterator, value_type);
 | 
						|
#else
 | 
						|
	iterator (container_type::* _F_insert_point)(const_iterator,
 | 
						|
						     value_type);
 | 
						|
#endif
 | 
						|
 | 
						|
	insert_base() : _F_insert_point(&container_type::insert) { }
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, by value.
 | 
						|
    template<typename _Tp1, typename _Tp2, typename _Tp3,
 | 
						|
	     template <typename, typename, typename> class _Tp4>
 | 
						|
      struct insert_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
 | 
						|
      {
 | 
						|
	typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
 | 
						|
                                                        container_type;
 | 
						|
	typedef typename container_type::iterator       iterator;
 | 
						|
	typedef typename container_type::const_iterator const_iterator;
 | 
						|
	typedef typename container_type::value_type     value_type;
 | 
						|
 | 
						|
	iterator (container_type::* _F_insert_point)(const_iterator,
 | 
						|
						     value_type);
 | 
						|
 | 
						|
	insert_base() : _F_insert_point(&container_type::insert) { }
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, as forward_list has insert_after.
 | 
						|
    template<typename _Tp1, typename _Tp2>
 | 
						|
      struct insert_base<std::forward_list<_Tp1, _Tp2>>
 | 
						|
      {
 | 
						|
	typedef std::forward_list<_Tp1, _Tp2> container_type;
 | 
						|
	typedef typename container_type::iterator 	iterator;
 | 
						|
	typedef typename container_type::const_iterator const_iterator;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
 | 
						|
	iterator (container_type::* _F_insert_point)(const_iterator,
 | 
						|
						     const value_type&);
 | 
						|
 | 
						|
	insert_base() : _F_insert_point(&container_type::insert_after) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_insert::value,
 | 
						|
			   bool = traits<_Tp>::has_insert_after::value>
 | 
						|
      struct insert_point;
 | 
						|
 | 
						|
    // Specialization for most containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct insert_point<_Tp, true, false> : public insert_base<_Tp>
 | 
						|
      {
 | 
						|
	typedef _Tp 				       	container_type;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
	using insert_base<_Tp>::_F_insert_point;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      (__test.*_F_insert_point)(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      (__test.*_F_insert_point)(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization for forward_list.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct insert_point<_Tp, false, true> : public insert_base<_Tp>
 | 
						|
      {
 | 
						|
	typedef _Tp 				       	container_type;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
	using insert_base<_Tp>::_F_insert_point;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.before_begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      (__test.*_F_insert_point)(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.before_begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      (__test.*_F_insert_point)(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct insert_point<_Tp, false, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_emplace::value
 | 
						|
				  && (traits<_Tp>::is_associative::value
 | 
						|
				      || traits<_Tp>::is_unordered::value)>
 | 
						|
      struct emplace;
 | 
						|
 | 
						|
    // Specialization for associative and unordered containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace<_Tp, true>
 | 
						|
      {
 | 
						|
	typedef _Tp					container_type;
 | 
						|
	typedef typename container_type::value_type	value_type;
 | 
						|
	typedef typename container_type::size_type	size_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.emplace(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      __test.emplace(cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::has_emplace::value,
 | 
						|
			   bool = traits<_Tp>::is_associative::value
 | 
						|
				  || traits<_Tp>::is_unordered::value,
 | 
						|
			   bool = traits<_Tp>::has_insert_after::value>
 | 
						|
      struct emplace_point;
 | 
						|
 | 
						|
    // Specialization for most containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace_point<_Tp, true, false, false>
 | 
						|
      {
 | 
						|
	typedef _Tp 				       	container_type;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization for associative and unordered containers.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace_point<_Tp, true, true, false>
 | 
						|
      {
 | 
						|
	typedef _Tp 				       	container_type;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace_hint(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace_hint(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization for forward_list.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct emplace_point<_Tp, true, false, true>
 | 
						|
      {
 | 
						|
	typedef _Tp 				       	container_type;
 | 
						|
	typedef typename container_type::value_type 	value_type;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.before_begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace_after(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	// Assumes containers start out equivalent.
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      const value_type cv = generate_unique<value_type>();
 | 
						|
	      const size_type sz = std::distance(__test.begin(), __test.end());
 | 
						|
	      size_type s = generate(sz);
 | 
						|
	      auto i = __test.before_begin();
 | 
						|
	      std::advance(i, s);
 | 
						|
	      __test.emplace_after(i, cv);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp, bool is_associative_or_unordered,
 | 
						|
			   bool has_insert_after>
 | 
						|
      struct emplace_point<_Tp, false, is_associative_or_unordered,
 | 
						|
			   has_insert_after>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::is_associative::value
 | 
						|
				  || traits<_Tp>::is_unordered::value>
 | 
						|
      struct clear
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      __container.clear();
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct clear<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
 | 
						|
      struct rehash
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      size_type s = generate(__test.bucket_count());
 | 
						|
	      __test.rehash(s);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __control, _Tp& __test)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      size_type s = generate(__test.bucket_count());
 | 
						|
	      __test.rehash(s);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    {
 | 
						|
	      // Also check hash status.
 | 
						|
	      bool fail(false);
 | 
						|
	      if (__control.load_factor() != __test.load_factor())
 | 
						|
		fail = true;
 | 
						|
	      if (__control.max_load_factor() != __test.max_load_factor())
 | 
						|
		fail = true;
 | 
						|
	      if (__control.bucket_count() != __test.bucket_count())
 | 
						|
		fail = true;
 | 
						|
	      if (__control.max_bucket_count() != __test.max_bucket_count())
 | 
						|
		fail = true;
 | 
						|
 | 
						|
	      if (fail)
 | 
						|
		{
 | 
						|
		  char buf[40];
 | 
						|
		  std::string __s("setup_base::rehash "
 | 
						|
				  "containers not equal");
 | 
						|
		  __s += "\n";
 | 
						|
		  __s += "\n";
 | 
						|
		  __s += "\t\t\tcontrol : test";
 | 
						|
		  __s += "\n";
 | 
						|
		  __s += "load_factor\t\t";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __control.load_factor());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += " : ";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __test.load_factor());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += "\n";
 | 
						|
 | 
						|
		  __s += "max_load_factor\t\t";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __control.max_load_factor());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += " : ";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __test.max_load_factor());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += "\n";
 | 
						|
 | 
						|
		  __s += "bucket_count\t\t";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __control.bucket_count());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += " : ";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __test.bucket_count());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += "\n";
 | 
						|
 | 
						|
		  __s += "max_bucket_count\t";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += " : ";
 | 
						|
		  __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
 | 
						|
		  __s += buf;
 | 
						|
		  __s += "\n";
 | 
						|
 | 
						|
		  std::__throw_logic_error(__s.c_str());
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 	}
 | 
						|
      };
 | 
						|
 | 
						|
    // Specialization, empty.
 | 
						|
    template<typename _Tp>
 | 
						|
      struct rehash<_Tp, false>
 | 
						|
      {
 | 
						|
	void
 | 
						|
	operator()(_Tp&) { }
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp&, _Tp&) { }
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct swap
 | 
						|
      {
 | 
						|
	_Tp _M_other;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      __container.swap(_M_other);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct iterator_operations
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::iterator       iterator;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      // Any will do.
 | 
						|
	      iterator i = __container.begin();
 | 
						|
	      iterator __attribute__((unused)) icopy(i);
 | 
						|
	      iterator __attribute__((unused)) iassign = i;
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct const_iterator_operations
 | 
						|
      {
 | 
						|
	typedef _Tp 					container_type;
 | 
						|
	typedef typename container_type::const_iterator	const_iterator;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      // Any will do.
 | 
						|
	      const_iterator i = __container.begin();
 | 
						|
	      const_iterator __attribute__((unused)) icopy(i);
 | 
						|
	      const_iterator __attribute__((unused)) iassign = i;
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
    template<typename _Tp>
 | 
						|
      struct assign_operator
 | 
						|
      {
 | 
						|
	_Tp _M_other;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      // An exception while assigning might leave the container empty
 | 
						|
	      // making future attempts less relevant. So we copy it before to
 | 
						|
	      // always assign to a non empty container. It also check for copy
 | 
						|
	      // constructor exception safety at the same time.
 | 
						|
	      _Tp __clone(__container);
 | 
						|
	      __clone = _M_other;
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
 | 
						|
 | 
						|
#if __cplusplus >= 201103L
 | 
						|
    template<typename _Tp>
 | 
						|
      struct move_assign_operator
 | 
						|
      {
 | 
						|
	_Tp _M_other;
 | 
						|
 | 
						|
	void
 | 
						|
	operator()(_Tp& __container)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      __container = std::move(_M_other);
 | 
						|
	    }
 | 
						|
	  catch(const __gnu_cxx::forced_error&)
 | 
						|
	    { throw; }
 | 
						|
	}
 | 
						|
      };
 | 
						|
#endif
 | 
						|
  };
 | 
						|
 | 
						|
  // Base class for exception tests.
 | 
						|
  template<typename _Tp>
 | 
						|
    struct test_base: public functor_base
 | 
						|
    {
 | 
						|
      typedef _Tp 					container_type;
 | 
						|
 | 
						|
      typedef functor_base				base_type;
 | 
						|
      typedef populate<container_type> 	       		populate;
 | 
						|
      typedef make_container_n<container_type> 	       	make_container_n;
 | 
						|
 | 
						|
      typedef clear<container_type> 		       	clear;
 | 
						|
      typedef erase_point<container_type> 	       	erase_point;
 | 
						|
      typedef erase_range<container_type> 	       	erase_range;
 | 
						|
      typedef insert_point<container_type> 	       	insert_point;
 | 
						|
      typedef emplace<container_type>			emplace;
 | 
						|
      typedef emplace_point<container_type>		emplace_point;
 | 
						|
      typedef emplace_front<container_type>		emplace_front;
 | 
						|
      typedef emplace_back<container_type>		emplace_back;
 | 
						|
      typedef pop_front<container_type> 	       	pop_front;
 | 
						|
      typedef pop_back<container_type> 			pop_back;
 | 
						|
      typedef push_front<container_type> 	       	push_front;
 | 
						|
      typedef push_back<container_type> 	       	push_back;
 | 
						|
      typedef rehash<container_type> 			rehash;
 | 
						|
      typedef swap<container_type> 			swap;
 | 
						|
      typedef iterator_operations<container_type>	iterator_ops;
 | 
						|
      typedef const_iterator_operations<container_type>	const_iterator_ops;
 | 
						|
      typedef assign_operator<container_type>		assign_operator;
 | 
						|
#if __cplusplus >= 201103L
 | 
						|
      typedef move_assign_operator<container_type>	move_assign_operator;
 | 
						|
#endif
 | 
						|
 | 
						|
      using base_type::compare;
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
  // Run through all member functions for basic exception safety
 | 
						|
  // guarantee: no resource leaks when exceptions are thrown.
 | 
						|
  //
 | 
						|
  // Types of resources checked: memory.
 | 
						|
  //
 | 
						|
  // For each member function, use throw_value and throw_allocator as
 | 
						|
  // value_type and allocator_type to force potential exception safety
 | 
						|
  // errors.
 | 
						|
  //
 | 
						|
  // NB: Assumes
 | 
						|
  // _Tp::value_type is __gnu_cxx::throw_value_*
 | 
						|
  // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
 | 
						|
  // And that the _Cond template parameter for them both is
 | 
						|
  // __gnu_cxx::limit_condition.
 | 
						|
  template<typename _Tp>
 | 
						|
    struct basic_safety : public test_base<_Tp>
 | 
						|
    {
 | 
						|
      typedef _Tp 					container_type;
 | 
						|
      typedef test_base<container_type>			base_type;
 | 
						|
      typedef typename base_type::populate 		populate;
 | 
						|
      typedef std::function<void(container_type&)> 	function_type;
 | 
						|
      typedef __gnu_cxx::limit_condition		condition_type;
 | 
						|
 | 
						|
      using base_type::generate;
 | 
						|
 | 
						|
      basic_safety() { run(); }
 | 
						|
 | 
						|
      void
 | 
						|
      run()
 | 
						|
      {
 | 
						|
	{
 | 
						|
	  // Setup.
 | 
						|
	  condition_type::never_adjustor off;
 | 
						|
 | 
						|
	  // Construct containers.
 | 
						|
	  container_type container;
 | 
						|
	  populate p1(container);
 | 
						|
 | 
						|
	  // Construct list of member functions to exercise.
 | 
						|
	  std::vector<function_type> functions;
 | 
						|
	  typename base_type::iterator_ops iops;
 | 
						|
	  functions.push_back(function_type(iops));
 | 
						|
	  typename base_type::const_iterator_ops ciops;
 | 
						|
	  functions.push_back(function_type(ciops));
 | 
						|
 | 
						|
	  typename base_type::erase_point erasep;
 | 
						|
	  functions.push_back(function_type(erasep));
 | 
						|
	  typename base_type::erase_range eraser;
 | 
						|
	  functions.push_back(function_type(eraser));
 | 
						|
	  typename base_type::insert_point insertp;
 | 
						|
	  functions.push_back(function_type(insertp));
 | 
						|
	  typename base_type::emplace emplace;
 | 
						|
	  functions.push_back(function_type(emplace));
 | 
						|
	  typename base_type::emplace_point emplacep;
 | 
						|
	  functions.push_back(function_type(emplacep));
 | 
						|
	  typename base_type::emplace_front emplacef;
 | 
						|
	  functions.push_back(function_type(emplacef));
 | 
						|
	  typename base_type::emplace_back emplaceb;
 | 
						|
	  functions.push_back(function_type(emplaceb));
 | 
						|
	  typename base_type::pop_front popf;
 | 
						|
	  functions.push_back(function_type(popf));
 | 
						|
	  typename base_type::pop_back popb;
 | 
						|
	  functions.push_back(function_type(popb));
 | 
						|
	  typename base_type::push_front pushf;
 | 
						|
	  functions.push_back(function_type(pushf));
 | 
						|
	  typename base_type::push_back pushb;
 | 
						|
	  functions.push_back(function_type(pushb));
 | 
						|
	  typename base_type::rehash rehash;
 | 
						|
	  functions.push_back(function_type(rehash));
 | 
						|
	  typename base_type::swap swap;
 | 
						|
	  populate p2(swap._M_other);
 | 
						|
	  functions.push_back(function_type(swap));
 | 
						|
	  typename base_type::assign_operator assignop;
 | 
						|
	  populate p3(assignop._M_other);
 | 
						|
	  functions.push_back(function_type(assignop));
 | 
						|
#if __cplusplus >= 201103L
 | 
						|
	  typename base_type::move_assign_operator massignop;
 | 
						|
	  populate p4(massignop._M_other);
 | 
						|
	  functions.push_back(function_type(massignop));
 | 
						|
#endif
 | 
						|
	  // Last.
 | 
						|
	  typename base_type::clear clear;
 | 
						|
	  functions.push_back(function_type(clear));
 | 
						|
 | 
						|
	  // Run tests.
 | 
						|
	  size_t i(1);
 | 
						|
	  for (auto it = functions.begin(); it != functions.end(); ++it)
 | 
						|
	    {
 | 
						|
	      function_type& f = *it;
 | 
						|
	      i = run_steps_to_limit(i, container, f);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	// Now that all instances has been destroyed check that there is no
 | 
						|
	// allocation remaining.
 | 
						|
	std::cout << "Checking remaining stuff" << std::endl;
 | 
						|
	__gnu_cxx::annotate_base::check();
 | 
						|
      }
 | 
						|
 | 
						|
      template<typename _Funct>
 | 
						|
	size_t
 | 
						|
	run_steps_to_limit(size_t __step, container_type& __cont,
 | 
						|
			   const _Funct& __f)
 | 
						|
	{
 | 
						|
	  bool exit(false);
 | 
						|
	  auto a = __cont.get_allocator();
 | 
						|
 | 
						|
	  do
 | 
						|
	    {
 | 
						|
	      // Use the current step as an allocator label.
 | 
						|
	      a.set_label(__step);
 | 
						|
 | 
						|
	      try
 | 
						|
		{
 | 
						|
		  condition_type::limit_adjustor limit(__step);
 | 
						|
		  __f(__cont);
 | 
						|
 | 
						|
		  // If we get here, done.
 | 
						|
		  exit = true;
 | 
						|
		}
 | 
						|
	      catch(const __gnu_cxx::forced_error&)
 | 
						|
		{
 | 
						|
		  // Check this step for allocations.
 | 
						|
		  // NB: Will throw std::logic_error if allocations.
 | 
						|
		  a.check(__step);
 | 
						|
 | 
						|
		  // Check memory allocated with operator new.
 | 
						|
 | 
						|
		}
 | 
						|
	      ++__step;
 | 
						|
	    }
 | 
						|
	  while (!exit);
 | 
						|
 | 
						|
	  // Log count info.
 | 
						|
	  std::cout << __f.target_type().name() << std::endl;
 | 
						|
	  std::cout << "end count " << __step << std::endl;
 | 
						|
	  return __step;
 | 
						|
	}
 | 
						|
  };
 | 
						|
 | 
						|
 | 
						|
  // Run through all member functions with a no throw requirement, sudden death.
 | 
						|
  // all: member functions erase, pop_back, pop_front, swap
 | 
						|
  //      iterator copy ctor, assignment operator
 | 
						|
  // unordered and associative: clear
 | 
						|
  // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
 | 
						|
  template<typename _Tp>
 | 
						|
    struct generation_prohibited : public test_base<_Tp>
 | 
						|
    {
 | 
						|
      typedef _Tp 					container_type;
 | 
						|
      typedef test_base<container_type>			base_type;
 | 
						|
      typedef typename base_type::populate 		populate;
 | 
						|
      typedef __gnu_cxx::random_condition		condition_type;
 | 
						|
 | 
						|
      generation_prohibited()  { run(); }
 | 
						|
 | 
						|
      void
 | 
						|
      run()
 | 
						|
      {
 | 
						|
	// Furthermore, assumes that the test functor will throw
 | 
						|
	// forced_exception via throw_allocator, that all errors are
 | 
						|
	// propagated and in error. Sudden death!
 | 
						|
 | 
						|
	// Setup.
 | 
						|
	container_type container;
 | 
						|
	typename base_type::swap swap;
 | 
						|
 | 
						|
	{
 | 
						|
	  condition_type::never_adjustor off;
 | 
						|
	  populate p1(container);
 | 
						|
	  populate p2(swap._M_other);
 | 
						|
	}
 | 
						|
 | 
						|
	// Run tests.
 | 
						|
	{
 | 
						|
	  condition_type::always_adjustor on;
 | 
						|
 | 
						|
	  // NB: Vector and deque are special, erase can throw if the copy
 | 
						|
	  // constructor or assignment operator of value_type throws.
 | 
						|
	  if (!traits<container_type>::has_throwing_erase::value)
 | 
						|
	    {
 | 
						|
	      typename base_type::erase_point erasep;
 | 
						|
	      erasep(container);
 | 
						|
	      typename base_type::erase_range eraser;
 | 
						|
	      eraser(container);
 | 
						|
	    }
 | 
						|
 | 
						|
	  typename base_type::pop_front popf;
 | 
						|
	  popf(container);
 | 
						|
	  typename base_type::pop_back popb;
 | 
						|
	  popb(container);
 | 
						|
 | 
						|
	  typename base_type::iterator_ops iops;
 | 
						|
	  iops(container);
 | 
						|
	  typename base_type::const_iterator_ops ciops;
 | 
						|
	  ciops(container);
 | 
						|
 | 
						|
	  swap(container);
 | 
						|
 | 
						|
	  // Last.
 | 
						|
	  typename base_type::clear clear;
 | 
						|
	  clear(container);
 | 
						|
	}
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
  // Test strong exception guarantee.
 | 
						|
  // Run through all member functions with a roll-back, consistent
 | 
						|
  // coherent requirement.
 | 
						|
  // all: member functions insert and emplace of a single element, push_back,
 | 
						|
  // push_front
 | 
						|
  // unordered: rehash
 | 
						|
  template<typename _Tp>
 | 
						|
    struct propagation_consistent : public test_base<_Tp>
 | 
						|
    {
 | 
						|
      typedef _Tp 					container_type;
 | 
						|
      typedef test_base<container_type>			base_type;
 | 
						|
      typedef typename base_type::populate 		populate;
 | 
						|
      typedef std::function<void(container_type&)> 	function_type;
 | 
						|
      typedef __gnu_cxx::limit_condition		condition_type;
 | 
						|
 | 
						|
      using base_type::compare;
 | 
						|
 | 
						|
      propagation_consistent() { run(); }
 | 
						|
 | 
						|
      // Run test.
 | 
						|
      void
 | 
						|
      run()
 | 
						|
      {
 | 
						|
	// Setup.
 | 
						|
	condition_type::never_adjustor off;
 | 
						|
 | 
						|
	// Construct containers.
 | 
						|
	container_type container_control;
 | 
						|
 | 
						|
	populate p(container_control);
 | 
						|
 | 
						|
	// Construct list of member functions to exercise.
 | 
						|
	std::vector<function_type> functions;
 | 
						|
	typename base_type::emplace emplace;
 | 
						|
	functions.push_back(function_type(emplace));
 | 
						|
	typename base_type::emplace_point emplacep;
 | 
						|
	functions.push_back(function_type(emplacep));
 | 
						|
	typename base_type::emplace_front emplacef;
 | 
						|
	functions.push_back(function_type(emplacef));
 | 
						|
	typename base_type::emplace_back emplaceb;
 | 
						|
	functions.push_back(function_type(emplaceb));
 | 
						|
	typename base_type::push_front pushf;
 | 
						|
	functions.push_back(function_type(pushf));
 | 
						|
	typename base_type::push_back pushb;
 | 
						|
	functions.push_back(function_type(pushb));
 | 
						|
	typename base_type::insert_point insertp;
 | 
						|
	functions.push_back(function_type(insertp));
 | 
						|
	typename base_type::rehash rehash;
 | 
						|
	functions.push_back(function_type(rehash));
 | 
						|
 | 
						|
	// Run tests.
 | 
						|
	for (auto i = functions.begin(); i != functions.end(); ++i)
 | 
						|
	  {
 | 
						|
	    function_type& f = *i;
 | 
						|
	    run_steps_to_limit(container_control, f);
 | 
						|
	  }
 | 
						|
      }
 | 
						|
 | 
						|
      template<typename _Funct>
 | 
						|
	void
 | 
						|
	run_steps_to_limit(container_type& container_control, const _Funct& __f)
 | 
						|
	{
 | 
						|
	  size_t i(1);
 | 
						|
	  bool exit(false);
 | 
						|
 | 
						|
	  do
 | 
						|
	    {
 | 
						|
	      container_type container_test(container_control);
 | 
						|
 | 
						|
	      try
 | 
						|
		{
 | 
						|
		  condition_type::limit_adjustor limit(i);
 | 
						|
		  __f(container_test);
 | 
						|
 | 
						|
		  // If we get here, done.
 | 
						|
		  exit = true;
 | 
						|
		}
 | 
						|
	      catch(const __gnu_cxx::forced_error&)
 | 
						|
		{
 | 
						|
		  compare(container_control, container_test);
 | 
						|
		  ++i;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	  while (!exit);
 | 
						|
 | 
						|
	  // Log count info.
 | 
						|
	  std::cout << __f.target_type().name() << std::endl;
 | 
						|
	  std::cout << "end count " << i << std::endl;
 | 
						|
	}
 | 
						|
    };
 | 
						|
 | 
						|
} // namespace __gnu_test
 | 
						|
 | 
						|
#endif
 |