Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
22 changes: 22 additions & 0 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,18 @@ struct inplace_vector
}
}

template <details::inplace_vector::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>>)
{
auto it = std::ranges::begin(rg);
const auto end = std::ranges::end(rg);
for (; size() != capacity() && it != end; ++it) {
unchecked_emplace_back(*it);
}
return it;
}

template <class... Args>
constexpr iterator emplace(const_iterator position, Args &&...args)
requires(std::constructible_from<T, Args...> && std::movable<T>)
Expand Down Expand Up @@ -717,6 +729,16 @@ struct inplace_vector
return *this;
}

constexpr inplace_vector &operator=(std::initializer_list<T> il)
requires(std::constructible_from<
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
std::movable<T>)
{
clear();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surely this is a pessimisation if the current is smaller than than the il -- of course we can't get the size of the initializer list because sometimes we're really dumb...

however we could perform the insert first and then only clear the elements needed -- hmm -- yeah idk this might be better. ugh

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think it matters much as for trivial type clear is just a setsize and for nontrivial it is setsize+destructor call (no memory allocation or other potential overhead).

Copy link
Member

@JeffGarland JeffGarland May 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well currently there's no optimization for trivial types -- which is a whole thing. it actually destroys all the elements.

edit: no it just erases, which doesn't destruct

edit2: So why isn't this simply assign_range( il );

Copy link
Collaborator Author

@20162026 20162026 May 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I will fix that, it definatly should have been assign_range...

also constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last) implementation might not be correct, but I will investigate it tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit: no it just erases, which doesn't destruct

What do you mean here

insert_range(begin(), il);
return *this;
}

constexpr void
swap(inplace_vector &x) noexcept(N == 0 ||
(std::is_nothrow_swappable_v<T> &&
Expand Down
1 change: 1 addition & 0 deletions tests/beman/inplace_vector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_gtest(compare)
add_gtest(constructors)
add_gtest(size_n_data)
add_gtest(erasure)
add_gtest(modifiers)

# constexpr test
add_executable(beman.inplace_vector.tests.constexpr constexpr.test.cpp)
Expand Down
40 changes: 37 additions & 3 deletions tests/beman/inplace_vector/modifiers.test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <numeric>

#include "gtest_setup.hpp"
#include <gtest/gtest.h>

namespace {
// 23.3.14.5 Modifiers [inplace.vector.modifiers]
Expand Down Expand Up @@ -581,8 +582,41 @@ TYPED_TEST(Modifiers, TryAppendRanges) {
// elements in the range begin() + [0, n) are not modified, and elements in
// the range begin() + [n, n + k) correspond to the inserted elements.

// TODO
GTEST_SKIP();
using IV = TestFixture::IV;
using T = TestFixture::T;
using size_type = IV::size_type;

IV device;
auto reference = this->unique();

device.try_append_range(reference | std::views::take(0));
EXPECT_EQ(device, IV());
device.clear();

EXPECT_EQ(device.try_append_range(reference), reference.end());
EXPECT_EQ(device, reference);
EXPECT_EQ(device.try_append_range(reference), reference.begin());
device.clear();

auto range = std::array<T, IV::capacity() + 1>{};
std::copy_n(reference.begin(), IV::capacity(), range.begin());
EXPECT_EQ(device.try_append_range(range), range.end() - 1);
EXPECT_EQ(device, reference);
device.clear();

auto half_size = std::midpoint(size_type(0), reference.size());
EXPECT_EQ(device.try_append_range(reference | std::views::take(half_size)),
reference.begin() + half_size);
EXPECT_EQ(device.try_append_range(reference | std::views::drop(half_size)),
reference.end());
EXPECT_EQ(device, reference);

device.clear();

EXPECT_EQ(device.try_append_range(reference | std::views::drop(half_size)),
reference.end());
EXPECT_EQ(device.try_append_range(reference), reference.begin() + half_size);
device.clear();
}

TYPED_TEST(Modifiers, UncheckedEmplacedBack) {
Expand Down