Skip to content

Commit da16ab7

Browse files
authored
Merge pull request #18 from neatudarius/P3168R1-iterator
P3168R1: use a non-pointer iterator type
2 parents eb9c83c + af42c10 commit da16ab7

31 files changed

+2761
-1054
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# /CMakeLists.txt -*-makefile-*-
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
14
cmake_minimum_required(VERSION 3.10)
25

36
project(beman_optional26 VERSION 0.0.0 LANGUAGES CXX)

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#! /usr/bin/make -f
2-
# -*-makefile-*-
2+
# /Makefile -*-makefile-*-
3+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
34

45
INSTALL_PREFIX?=.install/
56
PROJECT?=$(shell basename $(CURDIR))

README.md

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
# Beman.Optional26: C++26 Extensions for std::optional
22

3+
<!--
4+
SPDX-License-Identifier: 2.0 license with LLVM exceptions
5+
-->
6+
37
This implementation incorporates the C++26 extensions added for `std::optional`. The `Beman.Optional26` library aims to evaluate the stability, the usability, and the performance of these proposed changes before they are officially adopted by WG21 into the C++ Working Draft. Additionally, it allows developers to use these new features before they are implemented in major standard library compilers.
48

59
**Implements**:
10+
* [Give *std::optional* Range Support (P3168R1)](https://wg21.link/P3168R1)
611
* [`std::optional<T&>` (P2988R5)](https://wg21.link/P2988R5)
7-
* [Give *std::optional* Range Support (P3168R1)](https://wg21.link/P3168R1).
812

13+
## License
914

1015
Source is licensed with the Apache 2.0 license with LLVM exceptions
1116

@@ -21,8 +26,74 @@ The README itself is licesed with CC0 1.0 Universal. Copy the contents and incor
2126

2227
// SPDX-License-Identifier: CC0-1.0
2328

29+
## Examples
30+
31+
Full runable examples can be found in `examples/` - please check [./examples/README.md](./examples/README.md).
32+
33+
### range_loop
34+
35+
The next code snippet shows optional range support added in [Give *std::optional* Range Support (P3168R1)](https://wg21.link/P3168R1):
36+
37+
```cpp
38+
#include <Beman/Optional26/optional.hpp>
39+
...
40+
41+
// Example from P3168R1: basic range loop over C++26 optional.
42+
43+
beman::optional26::optional<int> empty_opt{};
44+
for ([[maybe_unused]] const auto& i : empty_opt) {
45+
// Should not see this in console.
46+
std::cout << "\"for each loop\" over C++26 optional: empty_opt\n";
47+
}
48+
49+
beman::optional26::optional<int> opt{26};
50+
for (const auto& i : opt) {
51+
// Should see this in console.
52+
std::cout << "\"for each loop\" over C++26 optional: opt = " << i << "\n";
53+
}
54+
```
55+
56+
Full code can be found in [./examples/range_loop.cpp](./examples/range_loop.cpp). Build and run instructions in [./examples/README.md](./examples/README.md).
57+
58+
### optional_ref
59+
60+
The next code snippet shows optional reference support added in [`std::optional<T&>` (P2988R5)](https://wg21.link/P2988R5):
61+
62+
```cpp
63+
#include <Beman/Optional26/optional.hpp>
64+
...
65+
66+
{
67+
// Empty optional example.
68+
std::optional<int> std_empty_opt;
69+
beman::optional26::optional<int> beman_empty_opt;
70+
assert(!std_empty_opt.has_value() &&
71+
!beman_empty_opt.has_value()); // or assert(!std_empty_opt && !beman_empty_opt);
72+
std::cout << "std_vs_beman: .has_value() matches?: "
73+
<< (std_empty_opt.has_value() == beman_empty_opt.has_value() ? "yes" : "no") << "\n";
74+
}
75+
76+
{
77+
// Optional with value example.
78+
std::optional<int> std_opt = 26;
79+
beman::optional26::optional<int> beman_opt = 26;
80+
assert(std_opt.has_value() && beman_opt.has_value()); // or assert(std_opt && beman_opt);
81+
assert(std_opt.value() == beman_opt.value()); // or assert(*std_opt == *beman_opt);
82+
std::cout << "std_vs_beman: .value() matches?: " << (std_opt.value() == beman_opt.value() ? "yes" : "no")
83+
<< "\n";
84+
}
85+
```
86+
87+
Full code can be found in [./examples/optional_ref.cpp](./examples/optional_ref.cpp). Build and run instructions in [./examples/README.md](./examples/README.md).
88+
2489
## How to Build
2590

91+
### Compiler Support
92+
93+
This is a modern C++ project which can be compiled with the latest C++ standards (**C++20 or later**).
94+
95+
Default build: `C++23`. Please check `etc/${compiler}-flags.cmake`.
96+
2697
### Dependencies
2798

2899
This project is mainly tested on `Ubuntu 22.04` and `Ubuntu 24.04`, but it should be as portable as CMake is. This project has zero C or C++ dependencies.
@@ -52,6 +123,8 @@ This project strives to be as normal and simple a CMake project as possible. Thi
52123

53124
```shell
54125
cmake --workflow --preset gcc-14
126+
cmake --workflow --preset clang-18
127+
cmake --workflow --preset systems # uses c++ set tool
55128
```
56129

57130
This should build and run the tests with GCC 14 with the address and undefined behavior sanitizers enabled.
@@ -69,6 +142,14 @@ The makefile will use your system compiler, `c++`, if no toolchain name is provi
69142
## Papers
70143

71144
Latest revision(s) of the papers can be built / found at:
72-
* [./papers/P2988/README.md](./papers/P2988/README.md) for `std::optional<T&> (P2988)`.
73145
* [give-std-optional-range-support](https://github.com/neatudarius/give-std-optional-range-support/) for `Give *std::optional* Range Support (P3168)`
74-
146+
* issue: [#1831](https://github.com/cplusplus/papers/issues/1831)
147+
* LEWG:
148+
* Reviewed in Tokyo 2024.
149+
* Forwarded by LEWG April electronic poll to LWG.
150+
* LWG:
151+
* To be reviewed in Saint Louis 2024.
152+
* [./papers/P2988/README.md](./papers/P2988/README.md) for `std::optional<T&> (P2988)`.
153+
* issue: [#1661](https://github.com/cplusplus/papers/issues/1661)
154+
* LEWG:
155+
* Reviewed in Tokyo 2024.

cmake/Config.cmake.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# cmake/Config.cmake.in -*-makefile-*-
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
14
@PACKAGE_INIT@
25

36
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")

etc/gcc-flags.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ include_guard(GLOBAL)
33
set(CMAKE_CXX_STANDARD 23)
44

55
set(CMAKE_CXX_FLAGS
6-
"-Wall -Wextra "
6+
"-std=c++23 -Wall -Wextra "
77
CACHE STRING "CXX_FLAGS" FORCE)
88

99
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fno-inline -g3" CACHE STRING "C++ DEBUG Flags" FORCE)

examples/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
# examples/CMakeLists.txt -*-makefile-*-
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
14
set(BEMAN_OPTIONAL26_LIBRARY "beman_optional26")
25

36
include(GNUInstallDirs)
47

58
# List of all buildable examples.
69
set(EXAMPLES
7-
sample
8-
range_loop
910
optional_ref
11+
pythagorean_triples
12+
range_loop
13+
sample
14+
std_vs_beman
1015
)
1116

1217
foreach(EXAMPLE ${EXAMPLES})

examples/README.md

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
# Beman.Optional26 Examples
22

3+
<!--
4+
SPDX-License-Identifier: 2.0 license with LLVM exceptions
5+
-->
6+
37
List of usage examples for `Beman.Optional26`.
48

9+
## License
10+
Source is licensed with the Apache 2.0 license with LLVM exceptions
11+
12+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
13+
14+
Documentation and associated papers are licensed with the Creative Commons Attribution 4.0 International license.
15+
16+
// SPDX-License-Identifier: CC-BY-4.0
17+
18+
The intent is that the source and documentation are available for use by people implementing their own optional types as well as people using the optional presented here as-is.
19+
20+
The README itself is licesed with CC0 1.0 Universal. Copy the contents and incorporate in your own work as you see fit.
21+
22+
// SPDX-License-Identifier: CC0-1.0
23+
524
## Sample
625

726
Check [sample](sample.cpp) for basic `Beman.Optional26` library usage.
@@ -11,32 +30,62 @@ Build and run instructions:
1130
# build
1231
$ cmake --workflow --preset gcc-14
1332

14-
# run sample
33+
# run sample.cpp
1534
$ .build/gcc-14/examples/RelWithDebInfo/sample
1635
empty_opt is empty!
1736
opt = 26
37+
38+
# run std_vs_beman.cpp
39+
$ .build/gcc-14/examples/RelWithDebInfo/std_vs_beman
40+
std_vs_beman: .has_value() matches?: yes
41+
std_vs_beman: .value() matches?: yes
1842
```
1943

2044
## Range Support (P3168R1)
2145

2246
Range support added in [*Give std::optional Range Support* (P3168R1)](https://wg21.link/P3168R1) examples:
2347
* [./range_loop.cpp](./range_loop.cpp)
48+
* [./pythagorean_triples.cpp](./pythagorean_triples.cpp)
2449

2550

2651
Build and run instructions:
2752

2853
```shell
29-
# build
30-
$ cmake --workflow --preset gcc-14
3154

32-
# run range_loop
55+
56+
# run range_loop.cpp
3357
$ .build/gcc-14/examples/RelWithDebInfo/range_loop
3458
# note: 1st log (empty_opt) is missing from console!
3559
"for each loop" over C++26 optional: opt = 26 # 2nd log (non empty opt)
60+
61+
# run pythagorean_triples.cpp
62+
$ .build/gcc-14/examples/RelWithDebInfo/pythagorean_triples
63+
First 10 Pythagorean triples:
64+
(3, 4, 5)
65+
(6, 8, 10)
66+
(5, 12, 13)
67+
(9, 12, 15)
68+
(8, 15, 17)
69+
(12, 16, 20)
70+
(7, 24, 25)
71+
(15, 20, 25)
72+
(10, 24, 26)
73+
(20, 21, 29)
74+
100th Pythagorean triple (x, y, z <= 200): (26, 168, 170)
3675
```
3776

3877
## Optional Reference (P2988R5)
3978

4079
Reference support added in [*std::optional<T&>*(P2988R5)](https://wg21.link/P2988R5) examples:
4180

4281
* [./optional_ref.cpp](./optional_ref.cpp)
82+
83+
Build and run instructions:
84+
85+
```shell
86+
# build
87+
$ cmake --workflow --preset gcc-14
88+
89+
# run optional_ref.cpp
90+
$ .build/gcc-14/examples/RelWithDebInfo/optional_ref
91+
```

examples/optional_ref.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,59 @@
1+
// examples/optional_ref.cpp -*-C++-*-
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
14
#include <Beman/Optional26/optional.hpp>
25

36
#include <string>
47

5-
using beman::optional::optional;
6-
78
struct Cat {
89
int catalog_index{0};
910
};
1011

11-
auto find_cat_old(std::string) -> Cat* { return nullptr; }
12+
namespace std17 {
13+
14+
// Prior to C++26, the code would look like this.
15+
// Using raw pointers to represent optional references.
16+
// Note: Using smart pointers would also be a choice, but it involves ownership semantics.
1217

13-
auto find_cat_new(std::string) -> optional<Cat&> { return optional<Cat&>{}; }
18+
Cat* find_cat(std::string) { return nullptr; }
1419

15-
Cat* doit_old(Cat& cat) { return &cat; }
16-
optional<Cat&> doit(Cat& cat) { return optional<Cat&>{cat}; }
20+
Cat* do_it(Cat& cat) { return &cat; }
1721

18-
Cat* before1() {
19-
Cat* cat = find_cat_old("Fido");
22+
Cat* api() {
23+
Cat* cat = find_cat("Fido");
2024
if (cat != nullptr) {
21-
return doit_old(*cat);
25+
return do_it(*cat);
2226
}
2327
return nullptr;
2428
}
2529

26-
optional<Cat&> after1() {
27-
optional<Cat&> cat = find_cat_new("Fido");
28-
return cat.and_then(doit);
30+
} // namespace std17
31+
32+
namespace std26 {
33+
// After C++26 with P2988R5, the code would look like this.
34+
// Using directly optional to represent optional references.
35+
36+
beman::optional26::optional<Cat&> find_cat(std::string) { return {}; }
37+
38+
beman::optional26::optional<Cat&> do_it(Cat& cat) { return {cat}; }
39+
40+
beman::optional26::optional<Cat&> api() {
41+
beman::optional26::optional<Cat&> cat = find_cat("Fido");
42+
return cat.and_then(do_it);
2943
}
3044

45+
} // namespace std26
46+
3147
int main() {
32-
Cat* cat_p = before1();
33-
optional<Cat&> cat_r = after1();
48+
// Example from P2988R5: optional reference.
49+
[[maybe_unused]] Cat* old_cat = std17::api();
50+
[[maybe_unused]] beman::optional26::optional<Cat&> new_cat = std26::api();
51+
52+
return 0;
3453
}
54+
55+
// # build example:
56+
// $ cmake --workflow --preset gcc-14
57+
//
58+
// # run example:
59+
// $ .build/gcc-14/examples/RelWithDebInfo/optional_ref

0 commit comments

Comments
 (0)