Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
akrzemi1 committed Oct 17, 2024
2 parents c151988 + c716bc5 commit e210740
Show file tree
Hide file tree
Showing 42 changed files with 613 additions and 1,387 deletions.
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ add_library(boost_optional INTERFACE)
add_library(Boost::optional ALIAS boost_optional)

target_include_directories(boost_optional INTERFACE include)
if(NOT CMAKE_VERSION VERSION_LESS "3.19")
file(GLOB_RECURSE headers include/*.hpp)
target_sources(boost_optional PRIVATE ${headers})
endif()

target_link_libraries(boost_optional
INTERFACE
Boost::assert
Boost::config
Boost::core
Boost::move
Boost::static_assert
Boost::throw_exception
Boost::type_traits
)
Expand Down
3 changes: 0 additions & 3 deletions build.jam
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ constant boost_dependencies :
/boost/assert//boost_assert
/boost/config//boost_config
/boost/core//boost_core
/boost/move//boost_move
/boost/static_assert//boost_static_assert
/boost/throw_exception//boost_throw_exception
/boost/type_traits//boost_type_traits ;

Expand All @@ -23,4 +21,3 @@ explicit

call-if : boost-library optional
;

26 changes: 17 additions & 9 deletions doc/00_optional.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,15 @@ Distributed under the Boost Software License, Version 1.0.
[def __SPACE__ [$images/space.png]]
[def __GO_TO__ [$images/R.png]]

[/ Common terms ]

[def __UB__ [@https://en.cppreference.com/w/cpp/language/ub ['undefined behavior]]]


[section Introduction]
Class template `optional` is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers. This is a header-only library.
Class template `optional` is a wrapper for representing 'optional' (or 'nullable')
objects who may not (yet) contain a valid value. Optional objects offer full value semantics;
they are good for passing by value and usage inside STL containers. This is a header-only C++11 library.

[heading Problem]
Suppose we want to read a parameter from a config file which represents some integral value, let's call it `"MaxValue"`. It is possible that this parameter is not specified; such situation is no error. It is valid to not specify the parameter and in that case the program is supposed to behave slightly differently. Also, suppose that any possible value of type `int` is a valid value for `"MaxValue"`, so we cannot just use `-1` to represent the absence of the parameter in the config file.
Expand All @@ -75,19 +81,16 @@ This is how you solve it with `boost::optional`:
[endsect]

[include 01_quick_start.qbk]
[section Tutorial]
[include 10_motivation.qbk]
[section:design Design Overview and Rationale]
[include 11_development.qbk]
[include 12_when_to_use.qbk]
[include 13_relational_operators.qbk]
[include 14_monadic_interface.qbk]
[include 12_relational_operators.qbk]
[include 13_convenience.qbk]
[include 15_io.qbk]
[include 16_optional_references.qbk]
[include 17_in_place_factories.qbk]
[include 18_gotchas.qbk]
[include 19_exception_safety.qbk]
[include 1A_type_requirements.qbk]
[include 1B_on_performance.qbk]
[endsect]
[section:reference Reference]
[include 21_ref_none.qbk]
Expand All @@ -100,6 +103,11 @@ This is how you solve it with `boost::optional`:
[endsect]
[include 29_ref_optional_convenience.qbk]
[endsect]
[section:advice Advice]
[include 31_when_to_use.qbk]
[include 32_on_performance.qbk]
[endsect]
[include 90_dependencies.qbk]
[include 91_relnotes.qbk]
[include 92_acknowledgments.qbk]
[include 91_comparison_with_std.qbk]
[include 92_relnotes.qbk]
[include 93_acknowledgments.qbk]
81 changes: 58 additions & 23 deletions doc/01_quick_start.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@
]


[section Quick Start]
[section Quick Overview]

[section Optional return values]

Let's write and use a converter function that converts a `std::string` to an `int`. It is possible that for a given string (e.g. `"cat"`) there exists no value of type `int` capable of representing the conversion result. We do not consider such situation an error. We expect that the converter can be used only to check if the conversion is possible. A natural signature for this function can be:
Let's write and use a converter function that converts a `std::string` to an `int`.
It is possible that for a given string (e.g. `"cat"`) there exists no value of type
`int` capable of representing the conversion result. We do not consider such
situation an error. We expect that the converter can be used only to check if
the conversion is possible. A natural signature for this function can be:

#include <boost/optional.hpp>
boost::optional<int> convert(const std::string& text);

All necessary functionality can be included with one header `<boost/optional.hpp>`. The above function signature means that the function can either return a value of type `int` or a flag indicating that no value of `int` is available. This does not indicate an error. It is like one additional value of `int`. This is how we can use our function:
All necessary functionality can be included with one header `<boost/optional.hpp>`.
The above function signature means that the function can either return a value
of type `int` or a flag indicating that no value of `int` is available.
This does not indicate an error. It is like one additional value of `int`.
This is how we can use our function:

const std::string& text = /*... */;
boost::optional<int> oi = convert(text); // move-construct
Expand Down Expand Up @@ -116,29 +124,10 @@ Suppose we want to implement a ['lazy load] optimization. This is because we do

`optional`'s default constructor creates an uninitialized optional. No call to `Resource`'s default constructor is attempted. `Resource` doesn't have to be __STD_DEFAULT_CONSTRUCTIBLE__. In function `getResource` we first check if `resource_` is initialized. This time we do not use the contextual conversion to `bool`, but a comparison with `boost::none`. These two ways are equivalent. Function `emplace` initializes the optional in-place by perfect-forwarding the arguments to the constructor of `Resource`. No copy- or move-construction is involved here. `Resource` doesn't even have to be `MoveConstructible`.

[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.tutorial.in_place_factories In-Place Factories].]
[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.design.in_place_factories In-Place Factories].]

[endsect]

[section Bypassing unnecessary default construction]

Suppose we have class `Date`, which does not have a default constructor: there is no good candidate for a default date. We have a function that returns two dates in form of a `boost::tuple`:

boost::tuple<Date, Date> getPeriod();

In other place we want to use the result of `getPeriod`, but want the two dates to be named: `begin` and `end`. We want to implement something like 'multiple return values':

Date begin, end; // Error: no default ctor!
boost::tie(begin, end) = getPeriod();

The second line works already, this is the capability of __BOOST_TUPLE__ library, but the first line won't work. We could set some invented initial dates, but it is confusing and may be an unacceptable cost, given that these values will be overwritten in the next line anyway. This is where `optional` can help:

boost::optional<Date> begin, end;
boost::tie(begin, end) = getPeriod();

It works because inside `boost::tie` a move-assignment from `T` is invoked on `optional<T>`, which internally calls a move-constructor of `T`.
[endsect]

[section Storage in containers]

Suppose you want to ask users to choose some number (an `int`). One of the valid responses is to choose nothing, which is represented by an uninitialized `optional<int>`. You want to make a histogram showing how many times each choice was made. You can use an `std::map`:
Expand All @@ -157,4 +146,50 @@ which is compared less than any value of `T`.
as it provides specializations for `std::hash`.
[endsect]

[section Monadic interface]

The monadic interface of `optional` allows the application of functions
to optional values without resorting to the usage of explicit `if`-statements.

Function `map` takes a function mapping type `T` onto type `U` and maps an `optional<T>`
onto an `optional<U>` using the provided function.

int length(const string& s){ return s.size(); };

optional<string> null{}, thin{""}, word{"word"};
assert (null.map(length) == none);
assert (thin.map(length) == 0);
assert (word.map(length) == 4);

Function `flat_map` is similar, but it requires the function to return an
`optional<V>` for some type `V`. This `optional<V>` becomes the return type of
`flat_map`.

optional<char> first_char(const string& s) {
if (s.empty()) return none;
else return s[0];
};

optional<string> null{}, thin{""}, word{"word"};
assert (null.flat_map(first_char) == none);
assert (thin.flat_map(first_char) == none);
assert (word.flat_map(first_char) == 'w');

These functions can be combined in one expression reflecting a chain of computations:

auto get_contents(path p) -> optional<string>;
auto trim(string) -> string;
auto length(string) -> int;

auto trimmed_size_of(optional<path> p) -> int
{
return p.flat_map(get_contents)
.map(trim)
.map(length)
.value_or(0);
}


[endsect]

[endsect]
80 changes: 0 additions & 80 deletions doc/10_motivation.qbk

This file was deleted.

Loading

0 comments on commit e210740

Please sign in to comment.