Skip to content
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
49c8304
Add freestanding build support
20162026 May 8, 2025
ea30ea5
Fix formatting
20162026 May 8, 2025
e3163fe
Remove exception check from freestanding-deleted
20162026 May 9, 2025
0f8f306
Formatting
20162026 May 9, 2025
f805280
Update assign_range
20162026 May 10, 2025
9859f3d
Merge branch 'main' into feature/freestanding
20162026 May 10, 2025
d907f23
Fix formatting
20162026 May 10, 2025
83f3635
update modifiers tests
wusatosi May 10, 2025
ddbc306
add freestanding test CI config
wusatosi May 10, 2025
9d97dfe
Make freestanding test work
wusatosi May 10, 2025
ac83154
Fix freestanding option
20162026 May 10, 2025
3695477
disable fib example on freestanding
wusatosi May 10, 2025
cf4f74d
Merge branch 'main' into feature/freestanding
20162026 May 11, 2025
b1a0692
Update freestanding tests
20162026 May 11, 2025
6918910
Merge branch 'main' into feature/freestanding
wusatosi May 21, 2025
4effc2b
Update tests/beman/inplace_vector/inplace_vector.test.cpp
wusatosi May 21, 2025
b5de692
fix merge issue
wusatosi May 21, 2025
567c6c1
fix merge issue
wusatosi May 21, 2025
8c81f1c
operator= is also freestanding delete
wusatosi May 22, 2025
329a2f2
fix non google-test tests
wusatosi May 22, 2025
32d1a8e
fix constexpr.test.cpp
wusatosi May 22, 2025
a691393
consistent naming
wusatosi May 22, 2025
ab78501
disable all freestanding function tests
wusatosi May 22, 2025
2567030
temporarily disabling all non-passing test units
wusatosi May 22, 2025
98c2e65
fix broken test
wusatosi May 22, 2025
a3e98e7
fix container_requirements.test.cpp
wusatosi May 22, 2025
097a961
add triviality tests back
wusatosi May 22, 2025
680e372
add constructor tests back
wusatosi May 22, 2025
be5dcf7
fix compare.test.cpp
wusatosi May 22, 2025
33e7759
add back size_n_data
wusatosi May 22, 2025
88fdb27
add erasure tests back
wusatosi May 22, 2025
79f6ce1
add modifier tests back
wusatosi May 22, 2025
c9eebca
add warning when BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS and BEMAN_INPLACE…
wusatosi May 22, 2025
b9f2c74
add noexceptions test
wusatosi May 22, 2025
57b4974
rename constructor.test.cpp as constructor_fs.test.cpp
wusatosi May 23, 2025
36bdf19
split container_requirement test into base and freestanding parts
wusatosi May 23, 2025
0cc0451
split modifier tests into base and freestanding tests
wusatosi May 23, 2025
4fef555
cleanup freestanding test
wusatosi May 23, 2025
110c222
split size_n_data test into base and freestanding tests
wusatosi May 23, 2025
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: 2 additions & 0 deletions .github/workflows/ci_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:
args: "-DCMAKE_CXX_FLAGS=-fsanitize=thread"
- description: "ASan"
args: "-DCMAKE_CXX_FLAGS='-fsanitize=address -fsanitize=undefined'"
- description: "delete freestanding"
args: "-DBEMAN_INPLACE_VECTOR_FREESTANDING_DELETED=ON"
- description: "NoExcep"
args: "-DBEMAN_INPLACE_VECTOR_NO_EXCEPTIONS=on"
include:
Expand Down
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ option(
${PROJECT_IS_TOP_LEVEL}
)

option(
BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED
"Enable freestanding mode. Default: OFF. Values: { ON, OFF }."
OFF
)

option(
BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS
"Disable exceptions by replacing throw calls with abort. Default: OFF. Values: { ON, OFF }."
Expand All @@ -52,6 +58,7 @@ target_include_directories(
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
$<INSTALL_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
)

# Install the InplaceVector library to the appropriate destination
Expand Down
6 changes: 5 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

set(ALL_EXAMPLES fibonacci)
set(ALL_EXAMPLES)

if(!BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED)
list(APPEND ALL_EXAMPLES fibonacci)
endif()

message("Examples to be built: ${ALL_EXAMPLES}")

Expand Down
6 changes: 4 additions & 2 deletions include/beman/inplace_vector/config.hpp.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef BEMAN_INPLACE_VECTOR_CONFIG_HPP
#define BEMAN_INPLACE_VECTOR_CONFIG_HPP
// include/beman/inplace_vector/config.hpp.in -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#cmakedefine01 BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()

#cmakedefine01 BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED()

#endif
126 changes: 60 additions & 66 deletions include/beman/inplace_vector/inplace_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
// Artifact from previous implementation, can be used as hints for optimizer
#define IV_EXPECT(EXPR)

#if BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED()
#define BEMAN_IV_FREESTANDING_DELETE(impl) = delete
#else
#define BEMAN_IV_FREESTANDING_DELETE(impl) impl
#endif

#ifndef BEMAN_IV_THROW_OR_ABORT
#if BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()
#include <cstdlib> // for abort
Expand All @@ -33,7 +39,6 @@
#include <stdexcept> // for length_error
#define BEMAN_IV_THROW_OR_ABORT(x) throw x
#endif
#endif

// beman::from_range_t
namespace beman {
Expand Down Expand Up @@ -271,11 +276,13 @@ struct inplace_vector
constexpr size_type size() const noexcept { return storage_size(); }
static constexpr size_type max_size() noexcept { return N; }
static constexpr size_type capacity() noexcept { return N; }
constexpr void reserve(size_type n) {

constexpr void reserve(size_type n) BEMAN_IV_FREESTANDING_DELETE({
if (n > N) [[unlikely]] {
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
}
}
});

constexpr void shrink_to_fit() {}

// element access
Expand Down Expand Up @@ -363,24 +370,23 @@ struct inplace_vector
template <class... Args>
constexpr T &emplace_back(Args &&...args)
requires(std::constructible_from<T, Args...>)
{
if (!try_emplace_back(std::forward<Args>(args)...)) [[unlikely]] {
BEMAN_IV_FREESTANDING_DELETE({
if (!try_emplace_back(std::forward<Args>(args)...)) [[unlikely]]
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
}
return back();
}
});
constexpr T &push_back(const T &x)
requires(std::constructible_from<T, const T &>)
{
BEMAN_IV_FREESTANDING_DELETE({
emplace_back(x);
return back();
}
});
constexpr T &push_back(T &&x)
requires(std::constructible_from<T, T &&>)
{
BEMAN_IV_FREESTANDING_DELETE({
emplace_back(std::forward<T &&>(x));
return back();
}
});

constexpr T *try_push_back(const T &x)
requires(std::constructible_from<T, const T &>)
Expand All @@ -407,7 +413,7 @@ struct inplace_vector
template <details::inplace_vector::container_compatible_range<T> R>
constexpr void append_range(R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
{
BEMAN_IV_FREESTANDING_DELETE({
if constexpr (std::ranges::sized_range<R>) {
if (size() + std::ranges::size(rg) > capacity()) [[unlikely]] {
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
Expand All @@ -419,7 +425,7 @@ struct inplace_vector
}
emplace_back(std::forward<decltype(e)>(e));
}
}
});

template <details::inplace_vector::container_compatible_range<T> R>
constexpr std::ranges::borrowed_iterator_t<R> try_append_range(R &&rg)
Expand All @@ -436,21 +442,21 @@ struct inplace_vector
template <class... Args>
constexpr iterator emplace(const_iterator position, Args &&...args)
requires(std::constructible_from<T, Args...> && std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
assert_iterator_in_range(position);
auto b = end();
emplace_back(std::forward<Args>(args)...);
auto pos = begin() + (position - begin());
std::rotate(pos, b, end());
return pos;
}
});

template <class InputIterator>
constexpr iterator insert(const_iterator position, InputIterator first,
InputIterator last)
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
assert_iterator_in_range(position);
if constexpr (std::random_access_iterator<InputIterator>) {
if (size() + static_cast<size_type>(std::distance(first, last)) >
Expand All @@ -464,85 +470,73 @@ struct inplace_vector
auto pos = begin() + (position - begin());
std::rotate(pos, b, end());
return pos;
}
});

template <details::inplace_vector::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>)
{
BEMAN_IV_FREESTANDING_DELETE({
return insert(position, std::begin(rg), std::end(rg));
}
});

constexpr iterator insert(const_iterator position,
std::initializer_list<T> il)
requires(std::constructible_from<
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
std::movable<T>)
{
return insert_range(position, il);
}
BEMAN_IV_FREESTANDING_DELETE({ return insert_range(position, il); });

constexpr iterator insert(const_iterator position, size_type n, const T &x)
requires(std::constructible_from<T, const T &> && std::copyable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
assert_iterator_in_range(position);
auto b = end();
for (size_type i = 0; i < n; ++i)
emplace_back(x);
auto pos = begin() + (position - begin());
std::rotate(pos, b, end());
return pos;
}
});

constexpr iterator insert(const_iterator position, const T &x)
requires(std::constructible_from<T, const T &> && std::copyable<T>)
{
return insert(position, 1, x);
}
BEMAN_IV_FREESTANDING_DELETE({ return insert(position, 1, x); });

constexpr iterator insert(const_iterator position, T &&x)
requires(std::constructible_from<T, T &&> && std::movable<T>)
{
return emplace(position, std::move(x));
}
BEMAN_IV_FREESTANDING_DELETE({ return emplace(position, std::move(x)); });

constexpr inplace_vector(std::initializer_list<T> il)
requires(std::constructible_from<
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
std::movable<T>)
{
insert(begin(), il);
}
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), il); });

constexpr inplace_vector(size_type n, const T &value)
requires(std::constructible_from<T, const T &> && std::copyable<T>)
{
insert(begin(), n, value);
}
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), n, value); });

constexpr explicit inplace_vector(size_type n)
requires(std::constructible_from<T, T &&> && std::default_initializable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
for (size_type i = 0; i < n; ++i)
emplace_back(T{});
}
});

template <class InputIterator> // BUGBUG: why not std::ranges::input_iterator?
constexpr inplace_vector(InputIterator first, InputIterator last)
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
std::movable<T>)
{
insert(begin(), first, last);
}
BEMAN_IV_FREESTANDING_DELETE({ insert(begin(), first, last); });

template <details::inplace_vector::container_compatible_range<T> R>
constexpr inplace_vector(beman::from_range_t, R &&rg)
requires(std::constructible_from<T, std::ranges::range_reference_t<R>> &&
std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
insert_range(begin(), std::forward<R &&>(rg));
}
});

constexpr iterator erase(const_iterator first, const_iterator last)
requires(std::movable<T>)
Expand All @@ -569,7 +563,7 @@ struct inplace_vector

constexpr void resize(size_type sz, const T &c)
requires(std::constructible_from<T, const T &> && std::copyable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
if (sz == size())
return;
else if (sz > N) [[unlikely]] {
Expand All @@ -580,10 +574,10 @@ struct inplace_vector
unsafe_destroy(begin() + sz, end());
unsafe_set_size(sz);
}
}
});
constexpr void resize(size_type sz)
requires(std::constructible_from<T, T &&> && std::default_initializable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
if (sz == size())
return;
else if (sz > N) [[unlikely]] {
Expand All @@ -595,20 +589,19 @@ struct inplace_vector
unsafe_destroy(begin() + sz, end());
unsafe_set_size(sz);
}
}
});

constexpr reference at(size_type pos) {
if (pos >= size()) [[unlikely]] {
constexpr reference at(size_type pos) BEMAN_IV_FREESTANDING_DELETE({
if (pos >= size()) [[unlikely]]
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
}
return details::inplace_vector::index(*this, pos);
}
constexpr const_reference at(size_type pos) const {
if (pos >= size()) [[unlikely]] {
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
}
return details::inplace_vector::index(*this, pos);
}
});
constexpr const_reference at(size_type pos) const
BEMAN_IV_FREESTANDING_DELETE({
if (pos >= size()) [[unlikely]]
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
return details::inplace_vector::index(*this, pos);
});

constexpr void pop_back() {
IV_EXPECT(size() > 0 && "pop_back from empty inplace_vector!");
Expand Down Expand Up @@ -702,31 +695,31 @@ struct inplace_vector
constexpr void assign(InputIterator first, InputIterator last)
requires(std::constructible_from<T, std::iter_reference_t<InputIterator>> &&
std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
clear();
insert(begin(), first, last);
}
});
template <details::inplace_vector::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>)
{
assign(std::begin(rg), std::end(rg));
}
BEMAN_IV_FREESTANDING_DELETE({
assign(std::ranges::begin(rg), std::ranges::end(rg));
});
constexpr void assign(size_type n, const T &u)
requires(std::constructible_from<T, const T &> && std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
clear();
insert(begin(), n, u);
}
});
constexpr void assign(std::initializer_list<T> il)
requires(std::constructible_from<
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
std::movable<T>)
{
BEMAN_IV_FREESTANDING_DELETE({
clear();
insert_range(begin(), il);
}
});

constexpr friend auto operator<=>(const inplace_vector &x,
const inplace_vector &y)
Expand Down Expand Up @@ -769,5 +762,6 @@ constexpr std::size_t erase_if(inplace_vector<T, N> &c, Predicate pred) {
} // namespace beman

#undef IV_EXPECT
#undef BEMAN_IV_FREESTANDING_DELETE

#endif // BEMAN_INPLACE_VECTOR_INPLACE_VECTOR_HPP
4 changes: 4 additions & 0 deletions tests/beman/inplace_vector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ add_gtest(size_n_data)
add_gtest(erasure)
add_gtest(modifiers)

if(BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED)
add_gtest(freestanding)
endif()

# only add noexception tests if NO_EXCEPTIONS option is set and compiler supports -fno-exceptions
if(
BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS
Expand Down
Loading
Loading