mirror of
				https://github.com/boostorg/unordered.git
				synced 2025-11-04 09:41:40 +01:00 
			
		
		
		
	* added concurrent node containers
* removed spurious typename
* added missing includes
* avoided unused param warning
* worked around Clang bug
* s/{}/() to work around GCC4.8 problems with aggregate initialization
* used /bigobj for cfoa/visit_tests.cpp
* suppressed localized maybe-uninitialized warnings
* fixed comments
* added /bigobj to cfoa/insert_tests.cpp
* instrumented double exact comparison to spot a spurious error
* fixed pedantic error
* refactored byte_span machinery
* compromised on sub-epsilon equality for doubles that should be identical
* documented boost::concurrent_node_(map|set)
* added concurrent_node_set
* added missing AlternativeType
* tested empty node insertion
* tested node_handle allocator management
* added nonassignable_allocator and node_handle_allocator_swap_tests
* fixed warning disabling
* silenced spurious GCC warning
* broadened scope of previous pragma
* broadened even more
* worked around spurious constexpr-related msvc-14.0 bug
https://godbolt.org/z/v78545Ebf
* added workaround back
* replaced previous workaround with built-in one
* added workaround back on top of built-in solution (which doesn't work 100% of the time)
		
	
		
			
				
	
	
		
			218 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (C) 2023 Christian Mazakas
 | 
						|
// Copyright (C) 2023-2024 Joaquin M Lopez Munoz
 | 
						|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
						|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
  
 | 
						|
#ifndef BOOST_UNORDERED_TEST_CFOA_COMMON_HELPERS_HPP
 | 
						|
#define BOOST_UNORDERED_TEST_CFOA_COMMON_HELPERS_HPP
 | 
						|
 | 
						|
#include <boost/unordered/concurrent_flat_map_fwd.hpp>
 | 
						|
#include <boost/unordered/concurrent_flat_set_fwd.hpp>
 | 
						|
#include <boost/unordered/concurrent_node_map_fwd.hpp>
 | 
						|
#include <boost/unordered/concurrent_node_set_fwd.hpp>
 | 
						|
#include <boost/unordered/unordered_flat_map.hpp>
 | 
						|
#include <boost/unordered/unordered_flat_set.hpp>
 | 
						|
#include <boost/unordered/unordered_node_map.hpp>
 | 
						|
#include <boost/unordered/unordered_node_set.hpp>
 | 
						|
 | 
						|
#include <cstddef>
 | 
						|
#include <type_traits>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
template <typename K>
 | 
						|
struct value_cardinality
 | 
						|
{
 | 
						|
  static constexpr std::size_t value=1;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename V>
 | 
						|
struct value_cardinality<std::pair<K, V> >
 | 
						|
{
 | 
						|
  static constexpr std::size_t value=2;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K>
 | 
						|
struct value_nonconst_cardinality
 | 
						|
{
 | 
						|
  static constexpr std::size_t value=1;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename V>
 | 
						|
struct value_nonconst_cardinality<std::pair<K, V> >
 | 
						|
{
 | 
						|
  static constexpr std::size_t value=
 | 
						|
    1 * !std::is_const<K>::value + 
 | 
						|
    1 * !std::is_const<V>::value ;
 | 
						|
};
 | 
						|
 | 
						|
template <class Container>
 | 
						|
struct is_container_node_based: std::false_type {};
 | 
						|
 | 
						|
template <typename K, typename V, typename H, typename P, typename A>
 | 
						|
struct is_container_node_based<boost::concurrent_node_map<K, V, H, P, A> >
 | 
						|
  : std::true_type {};
 | 
						|
 | 
						|
template <typename K, typename H, typename P, typename A>
 | 
						|
struct is_container_node_based<boost::concurrent_node_set<K, H, P, A> >
 | 
						|
  : std::true_type {};
 | 
						|
 | 
						|
template <class Container>
 | 
						|
struct reference_container_impl;
 | 
						|
 | 
						|
template <class Container>
 | 
						|
using reference_container = typename reference_container_impl<Container>::type;
 | 
						|
 | 
						|
template <typename K, typename V, typename H, typename P, typename A>
 | 
						|
struct reference_container_impl<boost::concurrent_flat_map<K, V, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_flat_map<K, V>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename V, typename H, typename P, typename A>
 | 
						|
struct reference_container_impl<boost::concurrent_node_map<K, V, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_node_map<K, V>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename H, typename P, typename A>
 | 
						|
struct reference_container_impl<boost::concurrent_flat_set<K, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_flat_set<K>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename H, typename P, typename A>
 | 
						|
struct reference_container_impl<boost::concurrent_node_set<K, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_node_set<K>;
 | 
						|
};
 | 
						|
 | 
						|
template <class Container>
 | 
						|
struct nonconcurrent_container_impl;
 | 
						|
 | 
						|
template <class Container>
 | 
						|
using nonconcurrent_container = 
 | 
						|
  typename nonconcurrent_container_impl<Container>::type;
 | 
						|
 | 
						|
template <typename K, typename V, typename H, typename P, typename A>
 | 
						|
struct nonconcurrent_container_impl<boost::concurrent_flat_map<K, V, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_flat_map<K, V, H, P, A>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename V, typename H, typename P, typename A>
 | 
						|
struct nonconcurrent_container_impl<boost::concurrent_node_map<K, V, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_node_map<K, V, H, P, A>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename H, typename P, typename A>
 | 
						|
struct nonconcurrent_container_impl<boost::concurrent_flat_set<K, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_flat_set<K, H, P, A>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K, typename H, typename P, typename A>
 | 
						|
struct nonconcurrent_container_impl<boost::concurrent_node_set<K, H, P, A> >
 | 
						|
{
 | 
						|
  using type = boost::unordered_node_set<K, H, P, A>;
 | 
						|
};
 | 
						|
 | 
						|
template <typename Container, template <typename> class Allocator>
 | 
						|
struct replace_allocator_impl;
 | 
						|
 | 
						|
template <typename Container, template <typename> class Allocator>
 | 
						|
using replace_allocator = 
 | 
						|
  typename replace_allocator_impl<Container, Allocator>::type;
 | 
						|
 | 
						|
template <
 | 
						|
  typename K, typename V, typename H, typename P, typename A,
 | 
						|
  template <typename> class Allocator
 | 
						|
>
 | 
						|
struct replace_allocator_impl<
 | 
						|
  boost::concurrent_flat_map<K, V, H, P, A>, Allocator>
 | 
						|
{
 | 
						|
  using value_type = 
 | 
						|
    typename boost::concurrent_flat_map<K, V, H, P, A>::value_type;
 | 
						|
  using type = 
 | 
						|
    boost::concurrent_flat_map<K, V, H, P, Allocator<value_type> >;
 | 
						|
};
 | 
						|
 | 
						|
template <
 | 
						|
  typename K, typename H, typename P, typename A,
 | 
						|
  template <typename> class Allocator
 | 
						|
>
 | 
						|
struct replace_allocator_impl<
 | 
						|
  boost::concurrent_flat_set<K, H, P, A>, Allocator>
 | 
						|
{
 | 
						|
  using value_type = 
 | 
						|
    typename boost::concurrent_flat_set<K, H, P, A>::value_type;
 | 
						|
  using type = 
 | 
						|
    boost::concurrent_flat_set<K, H, P, Allocator<value_type> >;
 | 
						|
};
 | 
						|
 | 
						|
template <
 | 
						|
  typename K, typename V, typename H, typename P, typename A,
 | 
						|
  template <typename> class Allocator
 | 
						|
>
 | 
						|
struct replace_allocator_impl<
 | 
						|
  boost::concurrent_node_map<K, V, H, P, A>, Allocator>
 | 
						|
{
 | 
						|
  using value_type = 
 | 
						|
    typename boost::concurrent_node_map<K, V, H, P, A>::value_type;
 | 
						|
  using type = 
 | 
						|
    boost::concurrent_node_map<K, V, H, P, Allocator<value_type> >;
 | 
						|
};
 | 
						|
 | 
						|
template <
 | 
						|
  typename K, typename H, typename P, typename A,
 | 
						|
  template <typename> class Allocator
 | 
						|
>
 | 
						|
struct replace_allocator_impl<
 | 
						|
  boost::concurrent_node_set<K, H, P, A>, Allocator>
 | 
						|
{
 | 
						|
  using value_type = 
 | 
						|
    typename boost::concurrent_node_set<K, H, P, A>::value_type;
 | 
						|
  using type = 
 | 
						|
    boost::concurrent_node_set<K, H, P, Allocator<value_type> >;
 | 
						|
};
 | 
						|
 | 
						|
template <typename K>
 | 
						|
K const& get_key(K const& x) { return x; }
 | 
						|
 | 
						|
template <typename K,typename V>
 | 
						|
K const& get_key(const std::pair<K, V>& x) { return x.first; }
 | 
						|
 | 
						|
template <typename K>
 | 
						|
K const& get_value(K const& x) { return x; }
 | 
						|
 | 
						|
template <typename K,typename V>
 | 
						|
V const& get_value(const std::pair<K, V>& x) { return x.second; }
 | 
						|
 | 
						|
template <typename K,typename V>
 | 
						|
V& get_value(std::pair<K, V>& x) { return x.second; }
 | 
						|
 | 
						|
template <class X, class Y>
 | 
						|
void test_matches_reference(X const& x, Y const& reference_cont)
 | 
						|
{
 | 
						|
  using value_type = typename X::value_type;
 | 
						|
  BOOST_TEST_EQ(x.size(), x.visit_all([&](value_type const& v) {
 | 
						|
    BOOST_TEST(reference_cont.contains(get_key(v)));
 | 
						|
    BOOST_TEST_EQ(v, *reference_cont.find(get_key(v)));
 | 
						|
  }));
 | 
						|
}
 | 
						|
 | 
						|
template <class X, class Y>
 | 
						|
void test_fuzzy_matches_reference(
 | 
						|
  X const& x, Y const& reference_cont, test::random_generator rg)
 | 
						|
{
 | 
						|
  using value_type = typename X::value_type;
 | 
						|
  BOOST_TEST_EQ(x.size(), x.visit_all([&](value_type const& v) {
 | 
						|
    BOOST_TEST(reference_cont.contains(get_key(v)));
 | 
						|
    if (rg == test::sequential) {
 | 
						|
      BOOST_TEST_EQ(v, *reference_cont.find(get_key(v)));
 | 
						|
    }
 | 
						|
  }));
 | 
						|
}
 | 
						|
 | 
						|
#endif // BOOST_UNORDERED_TEST_CFOA_COMMON_HELPERS_HPP
 |