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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Contributions are welcome.

#include <beman/inplace_vector/inplace_vector.hpp>

using namespace beman;
using namespace beman::inplace_vector;

/**
* Generates fibonacci sequence using inplace_vector.
Expand Down Expand Up @@ -93,21 +93,21 @@ Note this is not part of the standard Library and should not be relied on once
`constexpr` requirement stabilize.

Example Usage:
`static_assert(beman::has_constexpr_support<beman::inplace_vector<int, 5>>)`.
`static_assert(beman::has_constexpr_support<beman::inplace_vector::inplace_vector<int, 5>>)`.

### Freestanding

`beman::freestanding::inplace_vector` implements a minimal freestanding version of the specification,
`beman::inplace_vector::freestanding::inplace_vector` implements a minimal freestanding version of the specification,
which marks all potentially throwing functions as `= deleted`.
This is useful for platforms without exception support, as it will generate a compile-time error
instead of a potential runtime error when trying to use a throwing function.

``` C++
beman::inplace_vector<int, 1> iv;
beman::inplace_vector::inplace_vector<int, 1> iv;
iv.resize(0); // OK
iv.resize(10); // will throw or abort

beman::freestanding::inplace_vector<int, 1> fs_iv;
beman::inplace_vector::freestanding::inplace_vector<int, 1> fs_iv;
fs_iv.resize(0); // will generate a compile-time error
fs_iv.resize(10); // will generate a compile-time error
```
Expand Down
2 changes: 1 addition & 1 deletion examples/fibonacci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include <beman/inplace_vector/inplace_vector.hpp>

using namespace beman;
using namespace beman::inplace_vector;

/**
* Generates fibonacci sequence using inplace_vector.
Expand Down
78 changes: 33 additions & 45 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,11 @@
#endif
#endif

// beman::from_range_t
namespace beman {
// Private utilities
namespace beman::inplace_vector::details {

struct from_range_t {};
inline constexpr from_range_t from_range;
}; // namespace beman

// Private utilities
namespace beman::details::inplace_vector {

// clang-format off
// Smallest unsigned integer that can represent values in [0, N].
Expand Down Expand Up @@ -80,10 +77,7 @@ concept lessthan_comparable = requires(const T &a, const T &b) {
{ a < b } -> std::convertible_to<bool>;
};

} // namespace beman::details::inplace_vector

// Types implementing the `inplace_vector`'s storage
namespace beman::details::inplace_vector {
namespace storage {

// Storage for zero elements.
Expand Down Expand Up @@ -271,22 +265,20 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
// element access

constexpr reference operator[](size_type n) {
return details::inplace_vector::index(*this, n);
return details::index(*this, n);
}
constexpr const_reference operator[](size_type n) const {
return details::inplace_vector::index(*this, n);
}
constexpr reference front() {
return details::inplace_vector::index(*this, size_type(0));
return details::index(*this, n);
}
constexpr reference front() { return details::index(*this, size_type(0)); }
constexpr const_reference front() const {
return details::inplace_vector::index(*this, size_type(0));
return details::index(*this, size_type(0));
}
constexpr reference back() {
return details::inplace_vector::index(*this, size() - size_type(1));
return details::index(*this, size() - size_type(1));
}
constexpr const_reference back() const {
return details::inplace_vector::index(*this, size() - size_type(1));
return details::index(*this, size() - size_type(1));
}

// [containers.sequences.inplace_vector.data], data access
Expand Down Expand Up @@ -361,7 +353,7 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
return unchecked_emplace_back(std::forward<T &&>(x));
}

template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr std::ranges::borrowed_iterator_t<R> try_append_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
{
Expand Down Expand Up @@ -428,7 +420,7 @@ struct inplace_vector_base : private storage::storage_for<T, N> {

constexpr friend auto operator<=>(const inplace_vector_base &x,
const inplace_vector_base &y)
requires(beman::details::inplace_vector::lessthan_comparable<T>)
requires(details::lessthan_comparable<T>)
{
if constexpr (std::three_way_comparable<T>) {
return std::lexicographical_compare_three_way(x.begin(), x.end(),
Expand Down Expand Up @@ -514,19 +506,17 @@ struct inplace_vector_base : private storage::storage_for<T, N> {
}
};

} // namespace beman::details::inplace_vector
} // namespace beman::inplace_vector::details

namespace beman {
namespace beman::inplace_vector {

template <typename IV>
concept has_constexpr_support =
details::inplace_vector::satify_constexpr<typename IV::value_type,
IV::capacity()>;
details::satify_constexpr<typename IV::value_type, IV::capacity()>;

/// Dynamically-resizable fixed-N vector with inplace storage.
template <class T, size_t N>
struct inplace_vector
: public details::inplace_vector::inplace_vector_base<T, N> {
struct inplace_vector : public details::inplace_vector_base<T, N> {
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
Expand Down Expand Up @@ -563,7 +553,7 @@ struct inplace_vector
return this->back();
}

template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr void append_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
{
Expand Down Expand Up @@ -614,7 +604,7 @@ struct inplace_vector
return pos;
}

template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr iterator insert_range(const_iterator position, R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
Expand Down Expand Up @@ -672,7 +662,7 @@ struct inplace_vector
this->clear();
insert(this->begin(), first, last);
}
template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr void assign_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
Expand Down Expand Up @@ -738,13 +728,13 @@ struct inplace_vector
if (pos >= this->size()) [[unlikely]] {
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
}
return details::inplace_vector::index(*this, pos);
return details::index(*this, pos);
}
constexpr const_reference at(size_type pos) const {
if (pos >= this->size()) [[unlikely]] {
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
}
return details::inplace_vector::index(*this, pos);
return details::index(*this, pos);
}

// [containers.sequences.inplace_vector.cons], construct/copy/destroy
Expand Down Expand Up @@ -780,8 +770,8 @@ struct inplace_vector
insert(this->begin(), first, last);
}

template <details::inplace_vector::container_compatible_range<T> R>
constexpr inplace_vector(beman::from_range_t, R &&rg)
template <details::container_compatible_range<T> R>
constexpr inplace_vector(details::from_range_t, R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
{
Expand All @@ -791,8 +781,7 @@ struct inplace_vector

namespace freestanding {
template <class T, size_t N>
struct inplace_vector
: public details::inplace_vector::inplace_vector_base<T, N> {
struct inplace_vector : public details::inplace_vector_base<T, N> {
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
Expand All @@ -818,7 +807,7 @@ struct inplace_vector
requires(std::constructible_from<T, T &&>)
= delete;

template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr void append_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
= delete;
Expand All @@ -835,7 +824,7 @@ struct inplace_vector
std::movable<T>)
= delete;

template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr iterator insert_range(const_iterator position, R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
Expand Down Expand Up @@ -871,7 +860,7 @@ struct inplace_vector
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
std::movable<T>)
= delete;
template <details::inplace_vector::container_compatible_range<T> R>
template <details::container_compatible_range<T> R>
constexpr void assign_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
Expand Down Expand Up @@ -925,8 +914,8 @@ struct inplace_vector
std::movable<T>)
= delete;

template <details::inplace_vector::container_compatible_range<T> R>
constexpr inplace_vector(beman::from_range_t, R &&rg)
template <details::container_compatible_range<T> R>
constexpr inplace_vector(beman::inplace_vector::details::from_range_t, R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
= delete;
Expand All @@ -935,25 +924,24 @@ struct inplace_vector
} // namespace freestanding

template <typename T, std::size_t N, typename U = T>
constexpr std::size_t
erase(details::inplace_vector::inplace_vector_base<T, N> &c, const U &value) {
constexpr std::size_t erase(details::inplace_vector_base<T, N> &c,
const U &value) {
auto it = std::remove(c.begin(), c.end(), value);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;
}

template <typename T, std::size_t N, typename Predicate>
constexpr std::size_t
erase_if(details::inplace_vector::inplace_vector_base<T, N> &c,
Predicate pred) {
constexpr std::size_t erase_if(details::inplace_vector_base<T, N> &c,
Predicate pred) {
auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;
}

} // namespace beman
} // namespace beman::inplace_vector

#undef IV_EXPECT

Expand Down
4 changes: 2 additions & 2 deletions tests/beman/inplace_vector/compare.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <cmath>
#include <compare>

using namespace beman;
using namespace beman::inplace_vector;

template <class T>
concept has_threeway = requires(const T &t) {
Expand All @@ -13,7 +13,7 @@ concept has_threeway = requires(const T &t) {

template <class T>
concept lessthan_comparable =
beman::details::inplace_vector::lessthan_comparable<T>;
beman::inplace_vector::details::lessthan_comparable<T>;

template <typename T> struct vec_list {
T empty;
Expand Down
16 changes: 8 additions & 8 deletions tests/beman/inplace_vector/constexpr.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ struct Some {
};
static_assert(std::is_trivial_v<Some>);

using beman::has_constexpr_support;
using beman::inplace_vector;
using beman::inplace_vector::has_constexpr_support;
using beman::inplace_vector::inplace_vector;

static_assert(has_constexpr_support<inplace_vector<int, 50>>);
static_assert(has_constexpr_support<inplace_vector<Some, 50>>);
Expand All @@ -45,8 +45,8 @@ static_assert(!has_constexpr_support<inplace_vector<std::unique_ptr<int>, 50>>);

#define TEST(NAME) \
static_assert(std::invoke([]() { \
NAME<beman::inplace_vector<int, 20>>(); \
NAME<beman::inplace_vector<Some, 20>>(); \
NAME<beman::inplace_vector::inplace_vector<int, 20>>(); \
NAME<beman::inplace_vector::inplace_vector<Some, 20>>(); \
return true; \
}), \
"##NAME");
Expand All @@ -70,7 +70,7 @@ template <typename IV> constexpr void test_constructors() {
IV v(arr.begin(), arr.end());
}
{
IV v(beman::from_range_t{}, arr);
IV v(beman::inplace_vector::details::from_range_t{}, arr);
}
{
IV other{0, 1};
Expand Down Expand Up @@ -269,8 +269,8 @@ TEST(test_op_comp);

template <typename IV> constexpr void test_erase() {
IV v{0, 1, 2, 3, 3, 5};
(void)beman::erase(v, 3);
(void)beman::erase_if(v, [](auto v) { return v < 3; });
(void)beman::inplace_vector::erase(v, 3);
(void)beman::inplace_vector::erase_if(v, [](auto v) { return v < 3; });
}
TEST(test_erase)

Expand Down Expand Up @@ -298,7 +298,7 @@ static_assert(!has_constexpr_support<inplace_vector<Complex, 50>>);

template <typename T> constexpr void speical_test_empty() {
static_assert(!std::is_trivially_default_constructible_v<T>);
using IV = beman::inplace_vector<T, 0>;
using IV = beman::inplace_vector::inplace_vector<T, 0>;

std::array<T, 10> arr;
arr.fill(T{50});
Expand Down
12 changes: 7 additions & 5 deletions tests/beman/inplace_vector/constructors.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,30 +115,32 @@ TYPED_TEST(Constructors, CopyRanges) {
auto reference = this->unique();

{
IV device(beman::from_range, reference);
IV device(beman::inplace_vector::details::from_range, reference);
EXPECT_EQ(device, reference);
}

if (IV::capacity() == 0)
return;

{
IV device(beman::from_range, reference | std::ranges::views::take(1));
IV device(beman::inplace_vector::details::from_range,
reference | std::ranges::views::take(1));
EXPECT_EQ(device, IV{reference.front()});
}

{
auto mid = std::midpoint(0ul, reference.size());
IV device(beman::from_range, reference | std::ranges::views::take(mid));
IV device(beman::inplace_vector::details::from_range,
reference | std::ranges::views::take(mid));
EXPECT_EQ(device, IV(reference.begin(), reference.begin() + mid));
}
}

TYPED_TEST(Constructors, freestandingConversion) {
using T = TestFixture::T;

using IV = beman::inplace_vector<T, 5>;
using FS = beman::freestanding::inplace_vector<T, 5>;
using IV = beman::inplace_vector::inplace_vector<T, 5>;
using FS = beman::inplace_vector::freestanding::inplace_vector<T, 5>;

static_assert(std::is_constructible_v<FS, FS>);
static_assert(std::is_constructible_v<IV, IV>);
Expand Down
Loading