Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required (VERSION 3.15)
project (
small_vector
VERSION
0.10.1
0.10.2
LANGUAGES
CXX
)
Expand Down
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class GchSmallVectorConan(ConanFile):
name = "small_vector"
author = "Gene Harvey <gharveymn@gmail.com>"
version = "0.10.1"
version = "0.10.2"
license = "MIT"
url = "https://github.com/gharveymn/small_vector"
description = "A fully featured single header library implementing a vector container with a small buffer optimization."
Expand Down
4 changes: 2 additions & 2 deletions source/bench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ if (GCH_SMALL_VECTOR_BENCH_ENABLE_BOOST OR NOT DEFINED GCH_SMALL_VECTOR_BENCH_EN
endfunction ()

if (GCH_SMALL_VECTOR_BENCH_ENABLE_BOOST)
find_package (Boost REQUIRED COMPONENTS container)
find_package (Boost CONFIG REQUIRED COMPONENTS container)

check_boost_header (HAVE_BOOST_SMALL_VECTOR_HPP)

if (NOT HAVE_BOOST_SMALL_VECTOR_HPP)
message (FATAL_ERROR "Found Boost, but could not compile with boost/container/small_vector.hpp")
endif ()
else ()
find_package (Boost QUIET COMPONENTS container)
find_package (Boost CONFIG QUIET COMPONENTS container)

if (Boost_FOUND)
check_boost_header (HAVE_BOOST_SMALL_VECTOR_HPP QUIET)
Expand Down
117 changes: 95 additions & 22 deletions source/include/gch/small_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@
# endif
#endif

#if defined (__cpp_lib_to_address) && __cpp_lib_to_address >= 201711L
# ifndef GCH_LIB_TO_ADDRESS
# define GCH_LIB_TO_ADDRESS
# endif
#endif

// TODO:
// Make sure we don't need any laundering in the internal class functions.
// I also need some sort of test case to actually show where UB is occurring,
Expand Down Expand Up @@ -499,11 +505,26 @@ namespace gch
static_assert ( NullablePointer<int *>);
static_assert (! NullablePointer<int>);

template <typename I>
concept LegacyContiguousIterator =
std::random_access_iterator<I>
&& std::is_lvalue_reference<std::iter_reference_t<I>>::value
&& std::same_as<std::iter_value_t<I>, std::remove_cvref_t<std::iter_reference_t<I>>>
#ifdef GCH_LIB_TO_ADDRESS
&& requires (const I& i)
{
{ std::to_address (i) } -> std::same_as<std::add_pointer_t<std::iter_reference_t<I>>>;
}
#endif
;

template <typename A, typename T, typename U = T *>
concept AllocatorFor =
NoThrowCopyConstructible<A>
CopyConstructible<A>
&& requires (A a,
typename std::allocator_traits<A>::template rebind_alloc<U> b,
A a1,
A a2,
U xp,
typename std::allocator_traits<A>::pointer p,
typename std::allocator_traits<A>::const_pointer cp,
Expand All @@ -516,12 +537,12 @@ namespace gch
// A::pointer
requires NullablePointer< typename std::allocator_traits<A>::pointer>;
requires std::random_access_iterator<typename std::allocator_traits<A>::pointer>;
requires std::contiguous_iterator< typename std::allocator_traits<A>::pointer>;
requires LegacyContiguousIterator< typename std::allocator_traits<A>::pointer>;

// A::const_pointer
requires NullablePointer< typename std::allocator_traits<A>::const_pointer>;
requires std::random_access_iterator<typename std::allocator_traits<A>::const_pointer>;
requires std::contiguous_iterator< typename std::allocator_traits<A>::const_pointer>;
requires LegacyContiguousIterator< typename std::allocator_traits<A>::const_pointer>;

requires std::convertible_to<typename std::allocator_traits<A>::pointer,
typename std::allocator_traits<A>::const_pointer>;
Expand Down Expand Up @@ -618,8 +639,10 @@ namespace gch
|| requires { { a.destroy (xp) } -> std::convertible_to<void>; };

/** Relationship between instances **/
requires NoThrowConstructibleFrom<A, decltype (b)>;
requires NoThrowConstructibleFrom<A, decltype (std::move (b))>;
{ a1 == a2 } -> std::same_as<bool>;
{ a1 != a2 } -> std::same_as<bool>;
requires ConstructibleFrom<A, decltype (b)>;
requires ConstructibleFrom<A, decltype (std::move (b))>;

requires BoolConstant<typename std::allocator_traits<A>::is_always_equal>;

Expand All @@ -639,14 +662,6 @@ namespace gch

requires BoolConstant<
typename std::allocator_traits<A>::propagate_on_container_swap>;

{ a == b } -> std::same_as<bool>;
{ a != b } -> std::same_as<bool>;
}
&& requires (A a1, A a2)
{
{ a1 == a2 } -> std::same_as<bool>;
{ a1 != a2 } -> std::same_as<bool>;
};

static_assert (AllocatorFor<std::allocator<int>, int>,
Expand Down Expand Up @@ -5163,7 +5178,7 @@ namespace gch

GCH_CPP20_CONSTEXPR
small_vector (void)
noexcept (noexcept (allocator_type ()))
noexcept (std::is_nothrow_default_constructible<allocator_type>::value)
#ifdef GCH_LIB_CONCEPTS
requires concepts::DefaultConstructible<allocator_type>
#endif
Expand Down Expand Up @@ -5208,16 +5223,31 @@ namespace gch
{ }

GCH_CPP20_CONSTEXPR explicit
small_vector (size_type count, const allocator_type& alloc = allocator_type ())
small_vector (size_type count)
#ifdef GCH_LIB_CONCEPTS
requires DefaultInsertable && concepts::DefaultConstructible<allocator_type>
#endif
: small_vector (count, allocator_type ())
{ }

GCH_CPP20_CONSTEXPR explicit
small_vector (size_type count, const allocator_type& alloc)
#ifdef GCH_LIB_CONCEPTS
requires DefaultInsertable
#endif
: base (count, alloc)
{ }

GCH_CPP20_CONSTEXPR
small_vector (size_type count, const_reference value,
const allocator_type& alloc = allocator_type ())
small_vector (size_type count, const_reference value)
#ifdef GCH_LIB_CONCEPTS
requires CopyInsertable && concepts::DefaultConstructible<allocator_type>
#endif
: small_vector (count, value, allocator_type ())
{ }

GCH_CPP20_CONSTEXPR
small_vector (size_type count, const_reference value, const allocator_type& alloc)
#ifdef GCH_LIB_CONCEPTS
requires CopyInsertable
#endif
Expand All @@ -5228,20 +5258,38 @@ namespace gch
template <typename Generator>
requires std::invocable<Generator&>
&& EmplaceConstructible<std::invoke_result_t<Generator&>>::value
&& concepts::DefaultConstructible<allocator_type>
#else
template <typename Generator,
typename std::enable_if<
! std::is_convertible<Generator, const_reference>::value>::type * = nullptr>
! std::is_convertible<Generator, const_reference>::value
&&! std::is_convertible<Generator, const allocator_type&>::value>::type * = nullptr>
#endif
GCH_CPP20_CONSTEXPR
small_vector (size_type count, Generator g, const allocator_type& alloc = allocator_type ())
small_vector (size_type count, Generator g)
: small_vector (count, g, allocator_type ())
{ }

#ifdef GCH_LIB_CONCEPTS
template <typename Generator>
requires std::invocable<Generator&>
&& EmplaceConstructible<std::invoke_result_t<Generator&>>::value
#else
template <typename Generator,
typename std::enable_if<
! std::is_convertible<Generator, const_reference>::value
&&! std::is_convertible<Generator, const allocator_type&>::value>::type * = nullptr>
#endif
GCH_CPP20_CONSTEXPR
small_vector (size_type count, Generator g, const allocator_type& alloc)
: base (count, g, alloc)
{ }

#ifdef GCH_LIB_CONCEPTS
template <std::input_iterator InputIt>
requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
&& (std::forward_iterator<InputIt> || MoveInsertable)
&& concepts::DefaultConstructible<allocator_type>
#else
template <typename InputIt,
typename std::enable_if<
Expand All @@ -5251,13 +5299,38 @@ namespace gch
>::type * = nullptr>
#endif
GCH_CPP20_CONSTEXPR
small_vector (InputIt first, InputIt last, const allocator_type& alloc = allocator_type ())
small_vector (InputIt first, InputIt last)
: small_vector (first, last, allocator_type ())
{ }

#ifdef GCH_LIB_CONCEPTS
template <std::input_iterator InputIt>
requires EmplaceConstructible<std::iter_reference_t<InputIt>>::value
&& (std::forward_iterator<InputIt> || MoveInsertable)
#else
template <typename InputIt,
typename std::enable_if<
std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<InputIt>::iterator_category>::value
>::type * = nullptr>
#endif
GCH_CPP20_CONSTEXPR
small_vector (InputIt first, InputIt last, const allocator_type& alloc)
: base (first, last, typename std::iterator_traits<InputIt>::iterator_category { }, alloc)
{ }

GCH_CPP20_CONSTEXPR
small_vector (std::initializer_list<value_type> init,
const allocator_type& alloc = allocator_type ())
small_vector (std::initializer_list<value_type> init)
#ifdef GCH_LIB_CONCEPTS
requires EmplaceConstructible<const_reference>::value
&& concepts::DefaultConstructible<allocator_type>
#endif
: small_vector (init.begin (), init.end (), allocator_type ())
{ }

GCH_CPP20_CONSTEXPR
small_vector (std::initializer_list<value_type> init, const allocator_type& alloc)
#ifdef GCH_LIB_CONCEPTS
requires EmplaceConstructible<const_reference>::value
#endif
Expand Down
1 change: 1 addition & 0 deletions source/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,5 @@ endif ()

add_custom_target (small_vector.ctest)

add_subdirectory (integration)
add_subdirectory (unit)
4 changes: 4 additions & 0 deletions source/test/integration/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
find_package (Boost CONFIG QUIET COMPONENTS interprocess)
if (Boost_FOUND)
add_subdirectory (boost)
endif ()
16 changes: 16 additions & 0 deletions source/test/integration/boost/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
foreach (version ${GCH_SMALL_VECTOR_TEST_STANDARD_VERSIONS})
set (_TARGET_NAME small_vector.test.integration.boost.pmr_allocator.c++${version})
add_executable (${_TARGET_NAME} pmr_allocator.cpp)
target_link_libraries (${_TARGET_NAME} PRIVATE gch::small_vector Boost::boost)
target_compile_options (${_TARGET_NAME} PRIVATE "$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fconcepts-diagnostics-depth=100>")
set_target_properties (
${_TARGET_NAME}
PROPERTIES
CXX_STANDARD
${version}
CXX_STANDARD_REQUIRED
NO
CXX_EXTENSIONS
NO
)
endforeach ()
34 changes: 34 additions & 0 deletions source/test/integration/boost/pmr_allocator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <boost/interprocess/allocators/adaptive_pool.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <scoped_allocator>
#include <gch/small_vector.hpp>
#include <vector>

namespace bi = boost::interprocess;
using namespace gch;

template<class T>
using alloc = bi::adaptive_pool<T, bi::managed_shared_memory::segment_manager>;

using ipc_row = small_vector<int, default_buffer_size<alloc<int>>::value, alloc<int>>;
using scoped_alloc = std::scoped_allocator_adaptor<alloc<ipc_row>>;
using ipc_matrix = small_vector<ipc_row, default_buffer_size<scoped_alloc>::value, scoped_alloc>;

int main()
{
bi::managed_shared_memory s(bi::create_only, "Demo", 65536);

// create vector of vectors in shared memory
ipc_matrix v(s.get_segment_manager());

// for all these additions, the inner vectors obtain their allocator arguments
// from the outer vector's scoped_allocator_adaptor
v.resize(1);
v[0].push_back(1);
v.emplace_back(2);
// std::vector<int> local_row = {1, 2, 3};
small_vector<int> local_row = {1, 2, 3};
v.emplace_back(local_row.begin(), local_row.end());

bi::shared_memory_object::remove("Demo");
}