Skip to content

Commit 6918910

Browse files
authored
Merge branch 'main' into feature/freestanding
2 parents b1a0692 + aaa789e commit 6918910

File tree

13 files changed

+350
-118
lines changed

13 files changed

+350
-118
lines changed

.github/workflows/ci_tests.yml

Lines changed: 26 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,16 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
presets:
19-
- preset: "gcc-debug"
20-
platform: "ubuntu-latest"
21-
- preset: "gcc-release"
22-
platform: "ubuntu-latest"
23-
name: "Preset: ${{ matrix.presets.preset }} on ${{ matrix.presets.platform }}"
24-
runs-on: ${{ matrix.presets.platform }}
19+
- preset: gcc-debug
20+
tag: "gcc:14"
21+
- preset: gcc-release
22+
tag: "gcc:14"
23+
name: "Preset: ${{ matrix.presets.preset }}"
24+
runs-on: ubuntu-latest
25+
container:
26+
image: ghcr.io/bemanproject/testingcontainers-${{ matrix.presets.tag }}
2527
steps:
2628
- uses: actions/checkout@v4
27-
- name: Setup build environment
28-
uses: lukka/get-cmake@latest
29-
with:
30-
cmakeVersion: "~3.25.0"
31-
ninjaVersion: "^1.11.1"
3229
- name: Setup MSVC
3330
if: startsWith(matrix.presets.platform, 'windows')
3431
uses: TheMrMilchmann/setup-msvc-dev@v3
@@ -41,12 +38,13 @@ jobs:
4138
strategy:
4239
fail-fast: false
4340
matrix:
44-
platform: [ubuntu-24.04]
4541
compiler:
4642
- cpp: g++
4743
c: gcc
44+
tag: "gcc:14"
4845
- cpp: clang++
4946
c: clang
47+
tag: "clang:20"
5048
cpp_version: [20, 23]
5149
cmake_args:
5250
- description: "Default"
@@ -57,47 +55,30 @@ jobs:
5755
args: "-DCMAKE_CXX_FLAGS='-fsanitize=address -fsanitize=undefined'"
5856
- description: "delete freestanding"
5957
args: "-DBEMAN_INPLACE_VECTOR_FREESTANDING_DELETED=ON"
58+
- description: "NoExcep"
59+
args: "-DBEMAN_INPLACE_VECTOR_NO_EXCEPTIONS=on"
6060
include:
6161
- platform: ubuntu-24.04
6262
compiler:
6363
cpp: g++
6464
c: gcc
65+
tag: "gcc:14"
6566
cpp_version: 20
6667
cmake_args:
6768
description: "Dynamic"
6869
cmake_args: "-DBUILD_SHARED_LIBS=on"
6970

7071
name: "Build & Test: ${{ matrix.compiler.c }} ${{ matrix.cpp_version }} ${{ matrix.cmake_args.description }}"
71-
runs-on: ${{ matrix.platform }}
72+
runs-on: ubuntu-latest
73+
container:
74+
image: ghcr.io/bemanproject/testingcontainers-${{ matrix.compiler.tag }}
7275
steps:
7376
- uses: actions/checkout@v4
74-
- name: Install Ninja
75-
uses: lukka/get-cmake@latest
76-
with:
77-
cmakeVersion: "~3.25.0"
78-
ninjaVersion: "^1.11.1"
79-
- name: Install latest compiler
80-
run: |
81-
if [ "${{ matrix.compiler.cpp}}" == "g++" ]; then
82-
# Install gcc-14
83-
sudo apt-get update
84-
sudo apt-get install -y gcc-14 g++-14
85-
86-
sudo rm /usr/bin/gcc
87-
sudo ln -s /usr/bin/gcc-14 /usr/bin/gcc
88-
89-
sudo rm /usr/bin/g++
90-
sudo ln -s /usr/bin/g++-14 /usr/bin/g++
91-
else
92-
# Install llvm
93-
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
94-
fi
9577
- name: Print installed software
9678
run: |
97-
clang++ --version
98-
g++ --version
9979
cmake --version
10080
ninja --version
81+
ctest --version
10182
- name: Configure CMake
10283
run: |
10384
cmake -B build -S . -DCMAKE_CXX_STANDARD=${{ matrix.cpp_version }} ${{ matrix.cmake_args.args }}
@@ -128,44 +109,28 @@ jobs:
128109
fail-fast: false
129110
matrix:
130111
compilers:
131-
- class: gnu
112+
- class: gcc
132113
version: 14
133-
- class: gnu
114+
- class: gcc
134115
version: 13
135-
- class: gnu
116+
- class: gcc
136117
version: 12
137-
- class: llvm
118+
- class: clang
138119
version: 20
139-
- class: llvm
120+
- class: clang
140121
version: 19
141-
- class: llvm
122+
- class: clang
142123
version: 18
143-
- class: llvm
124+
- class: clang
144125
version: 17
145126
container:
146-
image: ghcr.io/wusatosi/cpp-docker:${{ matrix.compilers.class }}-${{ matrix.compilers.version }}
127+
image: ghcr.io/bemanproject/testingcontainers-${{ matrix.compilers.class }}:${{ matrix.compilers.version }}
147128
name: "Compiler: ${{ matrix.compilers.class }} ${{ matrix.compilers.version }}"
148129
steps:
149130
- uses: actions/checkout@v4
150-
- name: Install Compiler
151-
id: install-compiler
152-
run: |
153-
if [ "${{ matrix.compilers.class }}" = "gnu" ]; then
154-
CC=gcc-${{ matrix.compilers.version }}
155-
CXX=g++-${{ matrix.compilers.version }}
156-
else
157-
CC=clang-${{ matrix.compilers.version }}
158-
CXX=clang++-${{ matrix.compilers.version }}
159-
fi
160-
161-
echo "CC=$CC" >> "$GITHUB_OUTPUT"
162-
echo "CXX=$CXX" >> "$GITHUB_OUTPUT"
163131
- name: Configure CMake
164-
run: |
165-
cmake -B build -S . -DCMAKE_CXX_STANDARD=20
132+
run: cmake -B build -S . -DCMAKE_CXX_STANDARD=20
166133
env:
167-
CC: ${{ steps.install-compiler.outputs.CC }}
168-
CXX: ${{ steps.install-compiler.outputs.CXX }}
169134
CMAKE_GENERATOR: "Ninja Multi-Config"
170135
- name: Build Debug
171136
run: |

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ option(
3333
OFF
3434
)
3535

36+
option(
37+
BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS
38+
"Disable exceptions by replacing throw calls with abort. Default: OFF. Values: { ON, OFF }."
39+
OFF
40+
)
41+
3642
configure_file(
3743
"${PROJECT_SOURCE_DIR}/include/beman/inplace_vector/config.hpp.in"
3844
"${PROJECT_BINARY_DIR}/include/beman/inplace_vector/config.hpp"

include/beman/inplace_vector/config.hpp.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// include/beman/inplace_vector/config.hpp.in -*-C++-*-
22
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33

4-
#ifndef BEMAN_INPLACE_VECTOR_CONFIG_HPP
5-
#define BEMAN_INPLACE_VECTOR_CONFIG_HPP
4+
#cmakedefine01 BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()
65

76
#cmakedefine01 BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED()
87

include/beman/inplace_vector/inplace_vector.hpp

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
#ifndef BEMAN_INPLACE_VECTOR_INPLACE_VECTOR_HPP
44
#define BEMAN_INPLACE_VECTOR_INPLACE_VECTOR_HPP
55

6+
#if !defined(__has_include) || __has_include(<beman/inplace_vector/config.hpp>)
67
#include <beman/inplace_vector/config.hpp>
8+
#endif
79

810
#include <algorithm> // for rotate...
911
#include <array>
@@ -12,14 +14,12 @@
1214
#include <cstddef> // for size_t
1315
#include <cstdint> // for fixed-width integer types
1416
#include <cstdio> // for assertion diagnostics
15-
#include <cstdlib> // for abort
1617
#include <functional> // for less and equal_to
1718
#include <iterator> // for reverse_iterator and iterator traits
1819
#include <limits> // for numeric_limits
1920
#include <memory> // for destroy
2021
#include <new> // for operator new
2122
#include <ranges>
22-
#include <stdexcept> // for length_error
2323
#include <type_traits> // for aligned_storage and all meta-functions
2424

2525
// Artifact from previous implementation, can be used as hints for optimizer
@@ -31,6 +31,15 @@
3131
#define BEMAN_IV_FREESTANDING_DELETE(impl) impl
3232
#endif
3333

34+
#ifndef BEMAN_IV_THROW_OR_ABORT
35+
#if BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS()
36+
#include <cstdlib> // for abort
37+
#define BEMAN_IV_THROW_OR_ABORT(x) abort()
38+
#else
39+
#include <stdexcept> // for length_error
40+
#define BEMAN_IV_THROW_OR_ABORT(x) throw x
41+
#endif
42+
3443
// beman::from_range_t
3544
namespace beman {
3645
struct from_range_t {};
@@ -269,8 +278,9 @@ struct inplace_vector
269278
static constexpr size_type capacity() noexcept { return N; }
270279

271280
constexpr void reserve(size_type n) BEMAN_IV_FREESTANDING_DELETE({
272-
if (n > N) [[unlikely]]
273-
throw std::bad_alloc();
281+
if (n > N) [[unlikely]] {
282+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
283+
}
274284
});
275285

276286
constexpr void shrink_to_fit() {}
@@ -362,7 +372,7 @@ struct inplace_vector
362372
requires(std::constructible_from<T, Args...>)
363373
BEMAN_IV_FREESTANDING_DELETE({
364374
if (!try_emplace_back(std::forward<Args>(args)...)) [[unlikely]]
365-
throw std::bad_alloc();
375+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
366376
return back();
367377
});
368378
constexpr T &push_back(const T &x)
@@ -405,16 +415,30 @@ struct inplace_vector
405415
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
406416
BEMAN_IV_FREESTANDING_DELETE({
407417
if constexpr (std::ranges::sized_range<R>) {
408-
if (size() + std::ranges::size(rg) > capacity()) [[unlikely]]
409-
throw std::bad_alloc();
418+
if (size() + std::ranges::size(rg) > capacity()) [[unlikely]] {
419+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
420+
}
410421
}
411422
for (auto &&e : rg) {
412-
if (size() == capacity()) [[unlikely]]
413-
throw std::bad_alloc();
423+
if (size() == capacity()) [[unlikely]] {
424+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
425+
}
414426
emplace_back(std::forward<decltype(e)>(e));
415427
}
416428
});
417429

430+
template <details::inplace_vector::container_compatible_range<T> R>
431+
constexpr std::ranges::borrowed_iterator_t<R> try_append_range(R &&rg)
432+
requires(std::constructible_from<T, std::ranges::range_reference_t<R>>)
433+
{
434+
auto it = std::ranges::begin(rg);
435+
const auto end = std::ranges::end(rg);
436+
for (; size() != capacity() && it != end; ++it) {
437+
unchecked_emplace_back(*it);
438+
}
439+
return it;
440+
}
441+
418442
template <class... Args>
419443
constexpr iterator emplace(const_iterator position, Args &&...args)
420444
requires(std::constructible_from<T, Args...> && std::movable<T>)
@@ -436,8 +460,9 @@ struct inplace_vector
436460
assert_iterator_in_range(position);
437461
if constexpr (std::random_access_iterator<InputIterator>) {
438462
if (size() + static_cast<size_type>(std::distance(first, last)) >
439-
capacity()) [[unlikely]]
440-
throw std::bad_alloc{};
463+
capacity()) [[unlikely]] {
464+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
465+
}
441466
}
442467
auto b = end();
443468
for (; first != last; ++first)
@@ -541,9 +566,9 @@ struct inplace_vector
541566
BEMAN_IV_FREESTANDING_DELETE({
542567
if (sz == size())
543568
return;
544-
else if (sz > N) [[unlikely]]
545-
throw std::bad_alloc{};
546-
else if (sz > size())
569+
else if (sz > N) [[unlikely]] {
570+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
571+
} else if (sz > size())
547572
insert(end(), sz - size(), c);
548573
else {
549574
unsafe_destroy(begin() + sz, end());
@@ -555,26 +580,26 @@ struct inplace_vector
555580
BEMAN_IV_FREESTANDING_DELETE({
556581
if (sz == size())
557582
return;
558-
else if (sz > N) [[unlikely]]
559-
throw std::bad_alloc{};
560-
else if (sz > size())
583+
else if (sz > N) [[unlikely]] {
584+
BEMAN_IV_THROW_OR_ABORT(std::bad_alloc());
585+
} else if (sz > size()) {
561586
while (size() != sz)
562587
emplace_back(T{});
563-
else {
588+
} else {
564589
unsafe_destroy(begin() + sz, end());
565590
unsafe_set_size(sz);
566591
}
567592
});
568593

569594
constexpr reference at(size_type pos) BEMAN_IV_FREESTANDING_DELETE({
570595
if (pos >= size()) [[unlikely]]
571-
throw std::out_of_range("inplace_vector::at");
596+
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
572597
return details::inplace_vector::index(*this, pos);
573598
});
574599
constexpr const_reference at(size_type pos) const
575600
BEMAN_IV_FREESTANDING_DELETE({
576601
if (pos >= size()) [[unlikely]]
577-
throw std::out_of_range("inplace_vector::at");
602+
BEMAN_IV_THROW_OR_ABORT(std::out_of_range("inplace_vector::at"));
578603
return details::inplace_vector::index(*this, pos);
579604
});
580605

@@ -593,7 +618,7 @@ struct inplace_vector
593618
std::copyable<T>)
594619
{
595620
for (auto &&e : x)
596-
emplace_back(e);
621+
unchecked_emplace_back(e);
597622
}
598623

599624
constexpr inplace_vector(inplace_vector &&x)
@@ -605,7 +630,7 @@ struct inplace_vector
605630
std::movable<T>)
606631
{
607632
for (auto &&e : x)
608-
emplace_back(std::move(e));
633+
unchecked_emplace_back(std::move(e));
609634
}
610635

611636
constexpr inplace_vector &operator=(const inplace_vector &x)
@@ -623,7 +648,7 @@ struct inplace_vector
623648
{
624649
clear();
625650
for (auto &&e : x)
626-
emplace_back(e);
651+
unchecked_emplace_back(e);
627652
return *this;
628653
}
629654

@@ -642,7 +667,16 @@ struct inplace_vector
642667
{
643668
clear();
644669
for (auto &&e : x)
645-
emplace_back(std::move(e));
670+
unchecked_emplace_back(std::move(e));
671+
return *this;
672+
}
673+
674+
constexpr inplace_vector &operator=(std::initializer_list<T> il)
675+
requires(std::constructible_from<
676+
T, std::ranges::range_reference_t<std::initializer_list<T>>> &&
677+
std::movable<T>)
678+
{
679+
assign_range(il);
646680
return *this;
647681
}
648682

tests/beman/inplace_vector/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@ if(BEMAN_INPLACE_VECTOR_FREESTANDING_DELETED)
4747
add_gtest(freestanding)
4848
endif()
4949

50+
# only add noexception tests if NO_EXCEPTIONS option is set and compiler supports -fno-exceptions
51+
if(
52+
BEMAN_INPLACE_VECTOR_NO_EXCEPTIONS
53+
AND (
54+
CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
55+
OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
56+
)
57+
)
58+
add_gtest(noexceptions)
59+
target_compile_options(
60+
beman.inplace_vector.tests.noexceptions
61+
PRIVATE -fno-exceptions
62+
)
63+
endif()
64+
5065
# constexpr test
5166
add_executable(beman.inplace_vector.tests.constexpr constexpr.test.cpp)
5267
target_link_libraries(

0 commit comments

Comments
 (0)