2017-10-21 19:13:41 +01:00
# optional
2019-04-30 11:58:50 +01:00
2017-12-18 10:21:46 +00:00
Single header implementation of `std::optional` with functional-style extensions and support for references.
2017-10-02 14:21:25 +01:00
2019-04-30 11:59:11 +01:00
[](https://tl.tartanllama.xyz/en/latest/?badge=latest)
2017-10-21 20:36:56 +01:00
Clang + GCC: [](https://travis-ci.org/TartanLlama/optional)
MSVC: [](https://ci.appveyor.com/project/TartanLlama/optional)
2017-10-21 20:33:11 +01:00
2017-10-21 20:36:56 +01:00
`std::optional` is the preferred way to represent an object which may or may not have a value. Unfortunately, chaining together many computations which may or may not produce a value can be verbose, as empty-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `optional` cleaner.
2017-10-21 20:33:11 +01:00
2017-10-21 20:36:56 +01:00
For example, instead of writing this code:
2017-10-21 20:33:11 +01:00
2018-08-31 16:15:55 +02:00
```c++
2017-10-21 20:33:11 +01:00
std::optional< image > get_cute_cat (const image& img) {
auto cropped = crop_to_cat(img);
if (!cropped) {
return std::nullopt;
}
auto with_tie = add_bow_tie(*cropped);
if (!with_tie) {
return std::nullopt;
}
auto with_sparkles = make_eyes_sparkle(*with_tie);
if (!with_sparkles) {
return std::nullopt;
}
return add_rainbow(make_smaller(*with_sparkles));
}
```
You can do this:
2018-08-31 16:15:55 +02:00
```c++
2017-10-24 09:10:58 +01:00
tl::optional< image > get_cute_cat (const image& img) {
2017-10-21 20:33:11 +01:00
return crop_to_cat(img)
.and_then(add_bow_tie)
.and_then(make_eyes_sparkle)
.map(make_smaller)
.map(add_rainbow);
}
```
2017-10-21 19:15:33 +01:00
2017-10-21 20:36:56 +01:00
The interface is the same as `std::optional` , but the following member functions are also defined. Explicit types are for clarity.
- `map` : carries out some operation on the stored object if there is one.
* `tl::optional<std::size_t> s = opt_string.map(&std::string::size);`
- `and_then` : like `map` , but for operations which return a `tl::optional` .
* `tl::optional<int> stoi (const std::string& s);`
* `tl::optional<int> i = opt_string.and_then(stoi);`
- `or_else` : calls some function if there is no value stored.
2017-10-22 09:53:19 +01:00
* `opt.or_else([] { throw std::runtime_error{"oh no"}; });`
2017-10-21 20:36:56 +01:00
- `map_or` : carries out a `map` if there is a value, otherwise returns a default value.
* `tl::optional<std::size_t> s = opt_string.map_or(&std::string::size, 0);`
- `map_or_else` : carries out a `map` if there is a value, otherwise returns the result of a given default function.
* `std::size_t get_default();`
2019-09-16 19:56:05 +03:00
* `tl::optional<std::size_t> s = opt_string.map_or_else(&std::string::size, get_default);`
2017-10-21 20:36:56 +01:00
- `conjunction` : returns the argument if a value is stored in the optional, otherwise an empty optional.
* `tl::make_optional(42).conjunction(13); //13`
2019-09-16 19:56:05 +03:00
* `tl::optional<int>{}.conjunction(13); //empty`
2017-10-21 20:36:56 +01:00
- `disjunction` : returns the argument if the optional is empty, otherwise the current value.
* `tl::make_optional(42).disjunction(13); //42`
2017-10-22 09:53:43 +01:00
* `tl::optional<int>{}.disjunction(13); //13`
2017-10-21 20:36:56 +01:00
- `take` : returns the current value, leaving the optional empty.
* `opt_string.take().map(&std::string::size); //opt_string now empty;`
2017-10-11 19:09:06 +01:00
2017-12-18 10:21:46 +00:00
In addition to those member functions, optional references are also supported:
2018-08-31 16:15:55 +02:00
```c++
2017-12-18 10:21:46 +00:00
int i = 42;
tl::optional< int & > o = i;
*o == 42; //true
i = 12;
2019-09-16 19:56:05 +03:00
*o == 12; //true
2017-12-18 10:21:46 +00:00
& *o == &i; //true
```
Assignment has rebind semantics rather than assign-through semantics:
2018-08-31 16:15:55 +02:00
```c++
2017-12-18 10:21:46 +00:00
int j = 8;
o = j;
& *o == &j; //true
```
2017-10-11 19:09:06 +01:00
### Compiler support
Tested on:
2018-05-28 22:22:28 +01:00
- Linux
* clang 6.0.1
* clang 5.0.2
* clang 4.0.1
2017-10-21 21:57:59 +01:00
* clang 3.9
* clang 3.8
* clang 3.7
* clang 3.6
2017-10-21 22:36:09 +01:00
* clang 3.5
2018-05-28 22:22:28 +01:00
* g++ 8.0.1
* g++ 7.3
* g++ 6.4
2018-08-31 16:15:55 +02:00
* g++ 5.5
2017-10-21 22:21:49 +01:00
* g++ 4.9
2017-10-21 22:31:42 +01:00
* g++ 4.8
2018-05-28 22:22:28 +01:00
- Windows
2017-10-21 21:57:59 +01:00
* MSVC 2015
* MSVC 2017
2018-05-28 22:22:28 +01:00
2017-10-22 09:56:38 +01:00
### Standards Proposal
This library also serves as an implementation of WG21 standards paper [P0798R0: Monadic operations for std::optional ](https://wg21.tartanllama.xyz/monadic-optional ). This paper proposes adding `map` , `and_then` , and `or_else` to `std::optional` .
2017-10-21 22:40:52 +01:00
----------
[]("http://creativecommons.org/publicdomain/zero/1.0/")
2021-03-25 11:02:15 +00:00
To the extent possible under law, [Sy Brand ](https://twitter.com/TartanLlama ) has waived all copyright and related or neighboring rights to the `optional` library. This work is published from: United Kingdom.