Skip to content

Commit b268191

Browse files
authored
Merge branch 'main' into no-usenamespace-std
2 parents ae07149 + 5340a03 commit b268191

File tree

13 files changed

+2935
-21
lines changed

13 files changed

+2935
-21
lines changed

.github/workflows/ci_tests.yml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
c: gcc
3838
- cpp: clang++
3939
c: clang
40-
cpp_version: [23]
40+
cpp_version: [20, 23]
4141
cmake_args:
4242
- description: "Default"
4343
args: ""
@@ -50,15 +50,7 @@ jobs:
5050
compiler:
5151
cpp: g++
5252
c: gcc
53-
cpp_version: 23
54-
cmake_args:
55-
description: "Werror"
56-
args: "-DCMAKE_CXX_FLAGS='-Wall -Wextra -Wpedantic -Werror'"
57-
- platform: ubuntu-24.04
58-
compiler:
59-
cpp: g++
60-
c: gcc
61-
cpp_version: 23
53+
cpp_version: 20
6254
cmake_args:
6355
description: "Dynamic"
6456
cmake_args: "-DBUILD_SHARED_LIBS=on"

CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ option(
2727
${PROJECT_IS_TOP_LEVEL}
2828
)
2929

30+
include(FetchContent)
3031
include(GNUInstallDirs)
3132

3233
add_library(beman.inplace_vector INTERFACE)
@@ -59,6 +60,22 @@ install(
5960

6061
if(BEMAN_INPLACE_VECTOR_BUILD_TESTS)
6162
include(CTest)
63+
enable_testing()
64+
65+
# Fetch GoogleTest
66+
FetchContent_Declare(
67+
googletest
68+
GIT_REPOSITORY https://github.com/google/googletest.git
69+
GIT_TAG
70+
f8d7d77c06936315286eb55f8de22cd23c188571 # release-1.14.0
71+
EXCLUDE_FROM_ALL
72+
)
73+
74+
block()
75+
set(INSTALL_GTEST OFF) # Disable GoogleTest installation
76+
FetchContent_MakeAvailable(googletest)
77+
endblock()
78+
6279
add_subdirectory(tests/beman/inplace_vector)
6380
endif()
6481

include/beman/inplace_vector/inplace_vector.hpp

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ template <class = void>
313313
[[noreturn]]
314314
static constexpr void __assert_failure(char const *__file, int __line,
315315
char const *__msg) {
316-
if consteval {
316+
if (std::is_constant_evaluated()) {
317317
throw __msg; // TODO: std lib implementer, do better here
318318
} else {
319319
std::fprintf(stderr, "%s(%d): %s\n", __file, __line, __msg);
@@ -462,7 +462,11 @@ template <class __T, size_t __N> struct __non_trivial {
462462
constexpr __non_trivial &operator=(__non_trivial const &) noexcept = default;
463463
constexpr __non_trivial(__non_trivial &&) noexcept = default;
464464
constexpr __non_trivial &operator=(__non_trivial &&) noexcept = default;
465-
constexpr ~__non_trivial() = default;
465+
466+
constexpr ~__non_trivial()
467+
requires(is_trivially_destructible_v<__T>)
468+
= default;
469+
constexpr ~__non_trivial() { destroy(__data(), __data() + __size()); }
466470
};
467471

468472
// Selects the vector storage.
@@ -502,7 +506,7 @@ struct inplace_vector : private __iv_detail::__storage::_t<__T, __N> {
502506
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
503507

504508
// [containers.sequences.inplace_vector.cons], construct/copy/destroy
505-
constexpr inplace_vector() noexcept { __unsafe_set_size(0); }
509+
constexpr inplace_vector() noexcept = default;
506510
// constexpr explicit inplace_vector(size_type __n);
507511
// constexpr inplace_vector(size_type __n, const __T& __value);
508512
// template <class __InputIterator> // BUGBUG: why not model input_iterator?
@@ -697,11 +701,12 @@ struct inplace_vector : private __iv_detail::__storage::_t<__T, __N> {
697701
}
698702

699703
template <class... __Args>
700-
constexpr void emplace_back(__Args &&...__args)
704+
constexpr T &emplace_back(__Args &&...__args)
701705
requires(std::constructible_from<__T, __Args...>)
702706
{
703707
if (!try_emplace_back(std::forward<__Args>(__args)...)) [[unlikely]]
704708
throw std::bad_alloc();
709+
return back();
705710
}
706711
constexpr __T &push_back(const __T &__x)
707712
requires(std::constructible_from<__T, const __T &>)
@@ -773,7 +778,6 @@ struct inplace_vector : private __iv_detail::__storage::_t<__T, __N> {
773778
std::movable<__T>)
774779
{
775780
__assert_iterator_in_range(__position);
776-
__assert_valid_iterator_pair(__first, __last);
777781
if constexpr (std::random_access_iterator<__InputIterator>) {
778782
if (size() + static_cast<size_type>(std::distance(__first, __last)) >
779783
capacity()) [[unlikely]]
@@ -945,27 +949,60 @@ struct inplace_vector : private __iv_detail::__storage::_t<__T, __N> {
945949
}
946950

947951
constexpr inplace_vector(const inplace_vector &__x)
948-
requires(std::copyable<__T>)
952+
requires(__N == 0 || std::is_trivially_copy_constructible_v<__T>)
953+
= default;
954+
955+
constexpr inplace_vector(const inplace_vector &__x)
956+
requires(__N != 0 && !std::is_trivially_copy_constructible_v<__T> &&
957+
copyable<__T>)
949958
{
950959
for (auto &&__e : __x)
951960
emplace_back(__e);
952961
}
962+
953963
constexpr inplace_vector(inplace_vector &&__x)
954-
requires(std::movable<__T>)
964+
requires(__N == 0 || std::is_trivially_move_constructible_v<__T>)
965+
= default;
966+
967+
constexpr inplace_vector(inplace_vector &&__x)
968+
requires(__N != 0 && !std::is_trivially_move_constructible_v<__T> &&
969+
std::movable<__T>)
955970
{
956971
for (auto &&__e : __x)
957972
emplace_back(std::move(__e));
958973
}
974+
975+
constexpr inplace_vector &operator=(const inplace_vector &__x)
976+
requires(__N == 0 || (std::is_trivially_destructible_v<__T> &&
977+
std::is_trivially_copy_constructible_v<__T> &&
978+
std::is_trivially_copy_assignable_v<__T>))
979+
= default;
980+
959981
constexpr inplace_vector &operator=(const inplace_vector &__x)
960-
requires(std::copyable<__T>)
982+
requires(__N != 0 &&
983+
!(std::is_trivially_destructible_v<__T> &&
984+
std::is_trivially_copy_constructible_v<__T> &&
985+
std::is_trivially_copy_assignable_v<__T>) &&
986+
std::copyable<__T>)
961987
{
962988
clear();
963989
for (auto &&__e : __x)
964990
emplace_back(__e);
965991
return *this;
966992
}
993+
967994
constexpr inplace_vector &operator=(inplace_vector &&__x)
968-
requires(std::movable<__T>)
995+
requires(__N == 0 || (std::is_trivially_destructible_v<__T> &&
996+
std::is_trivially_move_constructible_v<__T> &&
997+
std::is_trivially_move_assignable_v<__T>))
998+
= default;
999+
1000+
constexpr inplace_vector &operator=(inplace_vector &&__x)
1001+
requires(__N != 0 &&
1002+
!(std::is_trivially_destructible_v<__T> &&
1003+
std::is_trivially_move_constructible_v<__T> &&
1004+
std::is_trivially_move_assignable_v<__T>) &&
1005+
std::movable<__T>)
9691006
{
9701007
clear();
9711008
for (auto &&__e : __x)

tests/beman/inplace_vector/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,23 @@ add_test(
2020
NAME beman.inplace_vector.ref-test
2121
COMMAND beman.inplace_vector.ref-test
2222
)
23+
24+
# GoogleTest based tests
25+
include(GoogleTest)
26+
27+
function(add_gtest NAME)
28+
add_executable(beman.inplace_vector.tests.${NAME})
29+
target_sources(beman.inplace_vector.tests.${NAME} PRIVATE ${NAME}.test.cpp)
30+
target_link_libraries(
31+
beman.inplace_vector.tests.${NAME}
32+
PRIVATE beman.inplace_vector GTest::gtest GTest::gtest_main
33+
)
34+
gtest_add_tests(beman.inplace_vector.tests.${NAME} "" AUTO)
35+
endfunction()
36+
37+
# Tests for official specs
38+
add_gtest(container_requirements)
39+
add_gtest(triviality)
40+
add_gtest(constructors)
41+
add_gtest(size_n_data)
42+
add_gtest(erasure)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Inplace Vector Testing Suite
2+
3+
This folder contains tests for `inplace_vector` implementation.
4+
5+
The aim for the test cases are to keep the implementation in-check with its standing in the latest C++ draft.
6+
7+
You can checkout `inplace_vector`'s current state in C++ draft [here](https://eel.is/c++draft/inplace.vector).
8+
9+
## C++ Draft paragraph to test file
10+
11+
`inplace_vector`'s chapter number in the latest C++ draft is **23.3.14**.
12+
13+
### Overview (23.3.14.1)
14+
15+
[Overview](https://eel.is/c++draft/inplace.vector#overview) has 6 clauses.
16+
17+
#### 6.1 Overview
18+
19+
> An inplace_vector is a contiguous container. Its capacity is fixed and its
20+
elements are stored within the inplace_vector object itself.
21+
22+
This is not testable.
23+
24+
#### 6.2 Container Requirements
25+
26+
> An inplace_vector meets all of the requirements of a container ([container.reqmts]),
27+
> of a reversible container ([container.rev.reqmts]), of a contiguous container,
28+
> and of a sequence container, including most of the optional sequence
29+
container requirements ([sequence.reqmts]). The exceptions are the push_front,
30+
> prepend_range, pop_front, and emplace_front member functions,
31+
> which are not provided.
32+
> Descriptions are provided here only for operations on inplace_vector that
33+
> are not described in one of these tables or for operations where there is
34+
> additional semantic information.
35+
36+
See [container_requirements.test.cpp](container_requirements.test.cpp).
37+
38+
#### 6.3 Constexpr Iterator
39+
40+
> For any N, `inplace_vector<T, N>​::​iterator` and
41+
> `inplace_vector<T, N>​::​const_iterator` meet the constexpr iterator
42+
> requirements.
43+
44+
Not tested for now.
45+
46+
#### 6.4 Constexpr member functions
47+
48+
> For any $N>0$, if T is not trivially copyable or
49+
> `is_trivially_default_constructible_v<T>` is false,
50+
> then no `inplace_vector<T, N>` member functions are usable in
51+
> constant expressions.
52+
53+
Not tested for now.
54+
55+
#### 6.5 Bad alloc requirement
56+
57+
> Any member function of `inplace_vector<T, N>` that would cause the size to
58+
> exceed N throws an exception of type bad_alloc.
59+
60+
These are tested with individual functions.
61+
62+
#### 6.6 Triviality
63+
64+
Let IV denote a specialization of `inplace_vector<T, N>`.
65+
> If N is zero, then IV is trivially copyable and empty,
66+
> and std​::​is_trivially_default_constructible_v<IV> is true.
67+
> (Sub-clauses omitted)
68+
69+
See [triviality.test.cpp](triviality.test.cpp)
70+
71+
### Constructors (23.3.14.2)
72+
73+
See [constructors.test.cpp](constructors.test.cpp)
74+
75+
### Size and capacity (23.3.14.3)
76+
77+
See [size_n_data.test.cpp](size_n_data.test.cpp)
78+
79+
### Data (23.3.14.4)
80+
81+
See [size_n_data.test.cpp](size_n_data.test.cpp)
82+
83+
### Modifiers (23.3.14.5)
84+
85+
See [modifiers.test.cpp](modifiers.test.cpp)
86+
87+
### Erasure (23.3.14.6)
88+
89+
See [erasure.test.cpp](erasure.test.cpp)
90+
91+
## Other tests
92+
93+
- [ref_impl.test.cpp](ref_impl.test.cpp):
94+
Is the test suite imported from reference implementation in
95+
[P0843R14](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0843r14.html).
96+
Originally included [here on godbolt](https://godbolt.org/z/5P78aG5xE).
97+
- [inplace_vector.test.cpp](inplace_vector.test.cpp):
98+
A minimal test suite by @Hels15 for their implementation.
99+
100+
## Known Issues/ Missed Tests
101+
102+
- Constexpr related functionalities.
103+
- Emplacement minimal copy/ construction.
104+
- Exception safety on mutation.
105+
106+
## Special Thanks
107+
108+
Special thanks to Jan Babst (@jbab) for his contribution at setting up the
109+
Google Test infrastructure.

0 commit comments

Comments
 (0)