/* Copyright 2025-2026 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_HUB_TEST_UTILITY_HPP #define BOOST_HUB_TEST_UTILITY_HPP #include #include #include #include #include #include template std::vector make_range(std::size_t n) { std::vector res; T i = T(); while(n--) { res.push_back(i); i += T(1); } return res; } struct null_callback { template void operator()(const T&) const {} }; template void puncture(Container& x, EraseCallback callback = EraseCallback()) { for(auto first = x.begin(); first != x.end(); ) { if(!(*first % 7)) { callback(first); first = x.erase(first); } else ++first; } } template struct rebind_value_type; template< template class Hub, typename T, typename Allocator, typename U > struct rebind_value_type, U> { //Use the container's resolved allocator_type rather than the Allocator //template argument, which may be void (the default that selects new_allocator). using type = Hub< U, typename boost::container::allocator_traits< typename Hub::allocator_type>:: template portable_rebind_alloc::type>; }; template using rebind_value_type_t = typename rebind_value_type::type; template struct rebind_allocator; template< template class Hub, typename T, typename Allocator, typename OtherAllocator > struct rebind_allocator, OtherAllocator> { using type = Hub< T, typename boost::container::allocator_traits:: template portable_rebind_alloc::type>; }; template using rebind_allocator_t = typename rebind_allocator::type; template struct reference_or_void { using type = T&; }; template<> struct reference_or_void { using type = void; }; template<> struct reference_or_void { using type = const void; }; template< typename T, typename Propagate = std::false_type, typename AlwaysEqual = std::false_type > struct stateful_allocator { using value_type = T; using propagate_on_container_copy_assignment = Propagate; using propagate_on_container_move_assignment = Propagate; using propagate_on_container_swap = Propagate; using is_always_equal = AlwaysEqual; /* typedefs and rebind required by not quite C++11-conformant * GCC < 5 stdlib. */ using pointer = T*; using const_pointer = const T*; using void_pointer = void*; using reference = typename reference_or_void::type; using const_reference = typename reference_or_void::type; using const_void_pointer = const void*; using difference_type = std::ptrdiff_t; using size_type = std::size_t; template struct rebind { using other = stateful_allocator; }; stateful_allocator(int state_ = 0): state{state_} {} template stateful_allocator(const stateful_allocator& x): state{x.state}, num_allocations{x.num_allocations} {} T* allocate(std::size_t n) { auto p = static_cast(::operator new(n * sizeof(T))); ++num_allocations; return p; } void deallocate(T* p, std::size_t) { ::operator delete(p); } bool operator==(const stateful_allocator& x) const { return AlwaysEqual::value || (state == x.state); } bool operator!=(const stateful_allocator& x) const { return !(*this == x); } int state; int num_allocations = 0; }; #endif