Skip to content

Commit 105f209

Browse files
authored
Merge pull request bemanproject#64 from frederick-vs-ja/constexpr-iterator
Make `contiguous_iterator` constexpr iterator
2 parents 4c5cd80 + 955f74d commit 105f209

File tree

6 files changed

+336
-244
lines changed

6 files changed

+336
-244
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ jobs:
1616
- {name: "Ubuntu Clang 18", os: ubuntu-24.04, toolchain: "clang-18", clang_version: 18, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "}
1717
# Note: clang-19 + Asan setup causes errors on some platforms. Temporary skip some checks via .asan_options.
1818
- {name: "Ubuntu Clang 19", os: ubuntu-24.04, toolchain: "clang-19", clang_version: 19, installed_clang_version: 17, cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" ", asan_options: "new_delete_type_mismatch=0"}
19-
- {name: "Ubuntu GCC 11", os: ubuntu-24.04, toolchain: "gcc-11", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "}
2019
- {name: "Ubuntu GCC 12", os: ubuntu-24.04, toolchain: "gcc-12", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "}
2120
- {name: "Ubuntu GCC 13", os: ubuntu-24.04, toolchain: "gcc-13", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "}
2221
- {name: "Ubuntu GCC 14", os: ubuntu-24.04, toolchain: "gcc-14", cmake_args: "-G \"Ninja Multi-Config\" -DCMAKE_CONFIGURATION_TYPES=\"RelWithDebInfo;Asan\" "}

etc/gcc-11-toolchain.cmake

Lines changed: 0 additions & 9 deletions
This file was deleted.

include/beman/optional26/detail/iterator.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,20 @@ struct contiguous_iterator : public base_contiguous_iterator<T, Container> {
4343
using typename base_type::reference;
4444

4545
// Default constructor.
46-
contiguous_iterator() noexcept : m_current() {}
46+
constexpr contiguous_iterator() noexcept : m_current() {}
4747

4848
// Pointer to iterator constructor.
49-
contiguous_iterator(pointer it) noexcept : m_current(it) {}
49+
constexpr contiguous_iterator(pointer it) noexcept : m_current(it) {}
5050

5151
// As per P2727R4, for contiguous iterator we only need to provide operator*, operator+= and operator-.
52-
reference operator*() const noexcept { return *m_current; }
53-
auto& operator+=(difference_type pos) noexcept {
52+
constexpr reference operator*() const noexcept { return *m_current; }
53+
constexpr auto& operator+=(difference_type pos) noexcept {
5454
m_current += pos;
5555
return *this;
5656
}
57-
difference_type operator-(contiguous_iterator other) const noexcept { return m_current - other.m_current; }
57+
constexpr difference_type operator-(contiguous_iterator other) const noexcept {
58+
return m_current - other.m_current;
59+
}
5860

5961
private:
6062
T* m_current;

src/beman/optional26/tests/detail/iterator.t.cpp

Lines changed: 90 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,27 @@
1010
#include <tests/test_types.hpp>
1111

1212
#include <concepts>
13+
#include <cstdlib>
1314
#include <type_traits>
1415
#include <set>
1516
#include <vector>
1617

17-
namespace beman::optional26::test {
18+
#define CONSTEXPR_EXPECT_EQ(val1, val2) \
19+
if (::std::is_constant_evaluated()) { \
20+
if (!((val1) == (val2))) { \
21+
::std::abort(); \
22+
} \
23+
} else \
24+
EXPECT_EQ(val1, val2)
25+
26+
namespace beman::optional26::tests {
1827

1928
// Dummy containers helper.
2029
struct container {};
2130

22-
} // namespace beman::optional26::test
31+
} // namespace beman::optional26::tests
2332

24-
using namespace beman::optional26::test;
33+
using namespace beman::optional26::tests;
2534

2635
TEST(IteratorTest, IteratorConcepts) {
2736
const auto test = [](auto&& it) {
@@ -53,88 +62,104 @@ TEST(IteratorTest, IteratorConcepts) {
5362
}
5463

5564
TEST(IteratorTest, DereferenceOperator) {
56-
std::vector<int> v{10, 20, 30, 40, 50};
57-
auto it = beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()};
65+
auto lambda = [&] {
66+
std::vector<int> v{10, 20, 30, 40, 50};
67+
auto it = beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()};
5868

59-
EXPECT_EQ(*it, 10);
60-
*it = 100;
61-
EXPECT_EQ(*it, 100);
69+
CONSTEXPR_EXPECT_EQ(*it, 10);
70+
*it = 100;
71+
CONSTEXPR_EXPECT_EQ(*it, 100);
6272

63-
it += 2;
64-
EXPECT_EQ(*it, 30);
73+
it += 2;
74+
CONSTEXPR_EXPECT_EQ(*it, 30);
6575

66-
*it = 300;
67-
EXPECT_EQ(*it, 300);
76+
*it = 300;
77+
CONSTEXPR_EXPECT_EQ(*it, 300);
78+
};
79+
static_assert((lambda(), true));
80+
lambda();
6881
}
6982

7083
TEST(IteratorTest, ForwardIterator) {
71-
std::vector<int> v{10, 20, 30, 40, 50};
72-
const std::vector<int> cv{10, 20, 30, 40, 50};
84+
auto lambda = [&] {
85+
std::vector<int> v{10, 20, 30, 40, 50};
86+
const std::vector<int> cv{10, 20, 30, 40, 50};
7387

74-
const auto test = [](auto&& it) {
75-
EXPECT_EQ(*it, 10);
88+
const auto test = [](auto&& it) {
89+
CONSTEXPR_EXPECT_EQ(*it, 10);
7690

77-
++it; // prefixed increment
78-
EXPECT_EQ(*it, 20);
91+
++it; // prefixed increment
92+
CONSTEXPR_EXPECT_EQ(*it, 20);
7993

80-
it++; // postfixed increment
81-
EXPECT_EQ(*it, 30);
94+
it++; // postfixed increment
95+
CONSTEXPR_EXPECT_EQ(*it, 30);
8296

83-
it++;
84-
EXPECT_EQ(*it, 40);
97+
it++;
98+
CONSTEXPR_EXPECT_EQ(*it, 40);
8599

86-
++it;
87-
EXPECT_EQ(*it, 50);
88-
};
100+
++it;
101+
CONSTEXPR_EXPECT_EQ(*it, 50);
102+
};
89103

90-
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
91-
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
104+
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
105+
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
106+
};
107+
static_assert((lambda(), true));
108+
lambda();
92109
}
93110

94111
TEST(IteratorTest, BidirectionalIterator) {
95-
std::vector<int> v{10, 20, 30, 40, 50};
96-
const std::vector<int> cv{10, 20, 30, 40, 50};
97-
const auto test = [](auto&& it) {
98-
it++;
99-
it++;
100-
EXPECT_EQ(*it, 30);
101-
102-
--it; // prefixed decrement
103-
EXPECT_EQ(*it, 20);
104-
105-
it--; // postfixed decrement
106-
EXPECT_EQ(*it, 10);
112+
auto lambda = [&] {
113+
std::vector<int> v{10, 20, 30, 40, 50};
114+
const std::vector<int> cv{10, 20, 30, 40, 50};
115+
const auto test = [](auto&& it) {
116+
it++;
117+
it++;
118+
CONSTEXPR_EXPECT_EQ(*it, 30);
119+
120+
--it; // prefixed decrement
121+
CONSTEXPR_EXPECT_EQ(*it, 20);
122+
123+
it--; // postfixed decrement
124+
CONSTEXPR_EXPECT_EQ(*it, 10);
125+
};
126+
127+
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
128+
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
107129
};
108-
109-
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
110-
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
130+
static_assert((lambda(), true));
131+
lambda();
111132
}
112133

113134
TEST(IteratorTest, RandomAccessIterator) {
114-
std::vector<int> v{10, 20, 30, 40, 50};
115-
const std::vector<int> cv{10, 20, 30, 40, 50};
116-
const auto test = [](auto&& it) {
117-
EXPECT_EQ(it[0], 10);
118-
EXPECT_EQ(it[1], 20);
119-
EXPECT_EQ(it[2], 30);
120-
EXPECT_EQ(it[3], 40);
121-
EXPECT_EQ(it[4], 50);
122-
123-
it += 2;
124-
EXPECT_EQ(*it, 30);
125-
126-
it -= 1;
127-
EXPECT_EQ(*it, 20);
128-
129-
it = it + 2;
130-
EXPECT_EQ(*it, 40);
131-
132-
it = it - 1;
133-
EXPECT_EQ(*it, 30);
135+
auto lambda = [&] {
136+
std::vector<int> v{10, 20, 30, 40, 50};
137+
const std::vector<int> cv{10, 20, 30, 40, 50};
138+
const auto test = [](auto&& it) {
139+
CONSTEXPR_EXPECT_EQ(it[0], 10);
140+
CONSTEXPR_EXPECT_EQ(it[1], 20);
141+
CONSTEXPR_EXPECT_EQ(it[2], 30);
142+
CONSTEXPR_EXPECT_EQ(it[3], 40);
143+
CONSTEXPR_EXPECT_EQ(it[4], 50);
144+
145+
it += 2;
146+
CONSTEXPR_EXPECT_EQ(*it, 30);
147+
148+
it -= 1;
149+
CONSTEXPR_EXPECT_EQ(*it, 20);
150+
151+
it = it + 2;
152+
CONSTEXPR_EXPECT_EQ(*it, 40);
153+
154+
it = it - 1;
155+
CONSTEXPR_EXPECT_EQ(*it, 30);
156+
};
157+
158+
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
159+
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
134160
};
135-
136-
test(beman::optional26::detail::contiguous_iterator<int, decltype(v)>{v.data()});
137-
test(beman::optional26::detail::contiguous_iterator<const int, decltype(v)>{cv.data()});
161+
static_assert((lambda(), true));
162+
lambda();
138163
}
139164

140165
TEST(IteratorTest, ContainerType) {

0 commit comments

Comments
 (0)