mirror of
				https://github.com/boostorg/unordered.git
				synced 2025-11-04 09:41:40 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			200 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
// Copyright 2008-2009 Daniel James.
 | 
						|
// Copyright 2024 Braden Ganetsky.
 | 
						|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
						|
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 | 
						|
#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD)
 | 
						|
#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD
 | 
						|
 | 
						|
#include <boost/core/lightweight_test.hpp>
 | 
						|
#include <boost/container_hash/hash.hpp>
 | 
						|
 | 
						|
namespace test {
 | 
						|
  struct object_count
 | 
						|
  {
 | 
						|
    int instances;
 | 
						|
    int constructions;
 | 
						|
 | 
						|
    object_count() : instances(0), constructions(0) {}
 | 
						|
    void reset() { *this = object_count(); }
 | 
						|
 | 
						|
    void construct()
 | 
						|
    {
 | 
						|
      ++instances;
 | 
						|
      ++constructions;
 | 
						|
    }
 | 
						|
 | 
						|
    void destruct()
 | 
						|
    {
 | 
						|
      if (instances == 0) {
 | 
						|
        BOOST_ERROR("Unbalanced constructions.");
 | 
						|
      } else {
 | 
						|
        --instances;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator==(object_count const& x) const
 | 
						|
    {
 | 
						|
      return instances == x.instances && constructions == x.constructions;
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator!=(object_count const& x) const { return !(*this == x); }
 | 
						|
 | 
						|
    friend std::ostream& operator<<(std::ostream& out, object_count const& c)
 | 
						|
    {
 | 
						|
      out << "[instances: " << c.instances
 | 
						|
          << ", constructions: " << c.constructions << "]";
 | 
						|
      return out;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // This won't be a problem as I'm only using a single compile unit
 | 
						|
  // in each test (this is actually require by the minimal test
 | 
						|
  // framework).
 | 
						|
  //
 | 
						|
  // boostinspect:nounnamed
 | 
						|
  namespace {
 | 
						|
    object_count global_object_count;
 | 
						|
  }
 | 
						|
 | 
						|
  struct counted_object
 | 
						|
  {
 | 
						|
    counted_object() { global_object_count.construct(); }
 | 
						|
    counted_object(counted_object const&) { global_object_count.construct(); }
 | 
						|
    ~counted_object() { global_object_count.destruct(); }
 | 
						|
  };
 | 
						|
 | 
						|
  struct check_instances
 | 
						|
  {
 | 
						|
    int instances_;
 | 
						|
    int constructions_;
 | 
						|
 | 
						|
    check_instances()
 | 
						|
        : instances_(global_object_count.instances),
 | 
						|
          constructions_(global_object_count.constructions)
 | 
						|
    {
 | 
						|
    }
 | 
						|
    ~check_instances()
 | 
						|
    {
 | 
						|
      BOOST_TEST(global_object_count.instances == instances_);
 | 
						|
    }
 | 
						|
 | 
						|
    int instances() const { return global_object_count.instances - instances_; }
 | 
						|
    int constructions() const
 | 
						|
    {
 | 
						|
      return global_object_count.constructions - constructions_;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  struct smf_count
 | 
						|
  {
 | 
						|
    int default_constructions = 0;
 | 
						|
    int copy_constructions = 0;
 | 
						|
    int move_constructions = 0;
 | 
						|
    int copy_assignments = 0;
 | 
						|
    int move_assignments = 0;
 | 
						|
    int destructions = 0;
 | 
						|
 | 
						|
#if (BOOST_CXX_VERSION < 201402L) || (defined(_MSC_VER) && _MSC_VER < 1910)
 | 
						|
    smf_count() = default;
 | 
						|
 | 
						|
    smf_count(int default_constructions_, int copy_constructions_,
 | 
						|
      int move_constructions_, int copy_assignments_, int move_assignments_,
 | 
						|
      int destructions_)
 | 
						|
        : default_constructions(default_constructions_),
 | 
						|
          copy_constructions(copy_constructions_),
 | 
						|
          move_constructions(move_constructions_),
 | 
						|
          copy_assignments(copy_assignments_),
 | 
						|
          move_assignments(move_assignments_), destructions(destructions_)
 | 
						|
    {
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    void reset() { *this = smf_count(); }
 | 
						|
 | 
						|
    void default_construct() { ++default_constructions; }
 | 
						|
    void copy_construct() { ++copy_constructions; }
 | 
						|
    void move_construct() { ++move_constructions; }
 | 
						|
    void copy_assign() { ++copy_assignments; }
 | 
						|
    void move_assign() { ++move_assignments; }
 | 
						|
    void destruct() { ++destructions; }
 | 
						|
 | 
						|
    friend bool operator==(smf_count const& lhs, smf_count const& rhs)
 | 
						|
    {
 | 
						|
      return lhs.default_constructions == rhs.default_constructions &&
 | 
						|
             lhs.copy_constructions == rhs.copy_constructions &&
 | 
						|
             lhs.move_constructions == rhs.move_constructions &&
 | 
						|
             lhs.copy_assignments == rhs.copy_assignments &&
 | 
						|
             lhs.move_assignments == rhs.move_assignments &&
 | 
						|
             lhs.destructions == rhs.destructions;
 | 
						|
    }
 | 
						|
 | 
						|
    friend std::ostream& operator<<(std::ostream& out, smf_count const& c)
 | 
						|
    {
 | 
						|
      out << "[default_constructions: " << c.default_constructions
 | 
						|
          << ", copy_constructions: " << c.copy_constructions
 | 
						|
          << ", move_constructions: " << c.move_constructions
 | 
						|
          << ", copy_assignments: " << c.copy_assignments
 | 
						|
          << ", move_assignments: " << c.move_assignments
 | 
						|
          << ", destructions: " << c.destructions << "]";
 | 
						|
      return out;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  template <class Tag> class smf_counted_object
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    static smf_count count;
 | 
						|
    static void reset_count() { count.reset(); }
 | 
						|
 | 
						|
    smf_counted_object(int index) : smf_counted_object() { index_ = index; }
 | 
						|
 | 
						|
    smf_counted_object() : index_(++running_index)
 | 
						|
    {
 | 
						|
      count.default_construct();
 | 
						|
    }
 | 
						|
    smf_counted_object(smf_counted_object const& rhs) : index_(rhs.index_)
 | 
						|
    {
 | 
						|
      count.copy_construct();
 | 
						|
    }
 | 
						|
    smf_counted_object(smf_counted_object&& rhs) noexcept : index_(rhs.index_)
 | 
						|
    {
 | 
						|
      count.move_construct();
 | 
						|
    }
 | 
						|
    smf_counted_object& operator=(smf_counted_object const& rhs)
 | 
						|
    {
 | 
						|
      count.copy_assign();
 | 
						|
      index_ = rhs.index_;
 | 
						|
      return *this;
 | 
						|
    }
 | 
						|
    smf_counted_object& operator=(smf_counted_object&& rhs) noexcept
 | 
						|
    {
 | 
						|
      count.move_assign();
 | 
						|
      index_ = rhs.index_;
 | 
						|
      return *this;
 | 
						|
    }
 | 
						|
    ~smf_counted_object() { count.destruct(); }
 | 
						|
 | 
						|
    friend bool operator==(
 | 
						|
      smf_counted_object const& lhs, smf_counted_object const& rhs)
 | 
						|
    {
 | 
						|
      return lhs.index_ == rhs.index_;
 | 
						|
    }
 | 
						|
 | 
						|
    friend std::size_t hash_value(smf_counted_object const& x)
 | 
						|
    {
 | 
						|
      return boost::hash<int>()(x.index_);
 | 
						|
    }
 | 
						|
 | 
						|
    int index_;
 | 
						|
 | 
						|
  private:
 | 
						|
    static int running_index;
 | 
						|
  };
 | 
						|
  template <class Tag> smf_count smf_counted_object<Tag>::count = {};
 | 
						|
  template <class Tag> int smf_counted_object<Tag>::running_index = 0;
 | 
						|
} // namespace test
 | 
						|
 | 
						|
#endif
 |