diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index 0693237..28532de 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -2,7 +2,7 @@ [quickbook 1.4] [authors [Cacciola Carballal, Fernando Luis]] [copyright 2003-2007 Fernando Luis Cacciola Carballal] - [copyright 2014 Andrzej Krzemieński] + [copyright 2014-2015 Andrzej Krzemieński] [category miscellaneous] [id optional] [dirname optional] @@ -80,16 +80,19 @@ This is how you solve it with `boost::optional`: [include 11_development.qbk] [include 12_when_to_use.qbk] [include 13_relational_operators.qbk] -[include 14_optional_references.qbk] -[include 15_in_place_factories.qbk] -[include 16_optional_bool.qbk] -[include 17_exception_safety.qbk] -[include 18_type_requirements.qbk] +[include 14_io.qbk] +[include 15_optional_references.qbk] +[include 16_in_place_factories.qbk] +[include 17_optional_bool.qbk] +[include 18_exception_safety.qbk] +[include 19_type_requirements.qbk] +[include 1A_on_performance.qbk] [endsect] [section Reference] [include 20_reference.qbk] [endsect] [include 90_dependencies.qbk] -[include 91_acknowledgments.qbk] +[include 91_relnotes.qbk] +[include 92_acknowledgments.qbk] diff --git a/doc/14_io.qbk b/doc/14_io.qbk new file mode 100644 index 0000000..0fb4e89 --- /dev/null +++ b/doc/14_io.qbk @@ -0,0 +1,37 @@ + +[section IO operators] + +It is possible to use `optional` with IO streams, provided that `T` can be used with streams. IOStream operators are defined in a separate header. + +`` +#include +#include + +int main() +{ + boost::optional o1 = 1, oN = boost::none; + std::cout << o1; + std::cin >> oN; +} +`` + +The current implementation does not guarantee any particular output. What it guarantees is that if streaming out and then back in `T` gives the same value, then streaming out and then back in `optional` will also give back the same result: + +`` +#include +#include +#include + +int main() +{ + boost::optional o1 = 1, oN = boost::none; + boost::optional x1, x2; + std::stringstream s; + s << o1 << oN; + s >> x1 >> x2; + assert (o1 == x1); + assert (oN == x2); +} +`` + +[endsect] diff --git a/doc/14_optional_references.qbk b/doc/15_optional_references.qbk similarity index 100% rename from doc/14_optional_references.qbk rename to doc/15_optional_references.qbk diff --git a/doc/15_in_place_factories.qbk b/doc/16_in_place_factories.qbk similarity index 100% rename from doc/15_in_place_factories.qbk rename to doc/16_in_place_factories.qbk diff --git a/doc/16_optional_bool.qbk b/doc/17_optional_bool.qbk similarity index 100% rename from doc/16_optional_bool.qbk rename to doc/17_optional_bool.qbk diff --git a/doc/17_exception_safety.qbk b/doc/18_exception_safety.qbk similarity index 100% rename from doc/17_exception_safety.qbk rename to doc/18_exception_safety.qbk diff --git a/doc/18_type_requirements.qbk b/doc/19_type_requirements.qbk similarity index 100% rename from doc/18_type_requirements.qbk rename to doc/19_type_requirements.qbk diff --git a/doc/1A_on_performance.qbk b/doc/1A_on_performance.qbk new file mode 100644 index 0000000..841190f --- /dev/null +++ b/doc/1A_on_performance.qbk @@ -0,0 +1,131 @@ + +[section Performance considerations] + +Technical details aside, the memory layout of `optional` is more-less this: + + template + class optional + { + bool _initialized; + std::aligned_storage_t _storage; + }; + +But for the purpose of this analysis, considering memory layouts, we can think of it as: + + template + class optional + { + bool _initialized; + T _storage; + }; + +Given type `optional`, and assuming that `sizeof(int) == 4`, we will get `sizeof(optional) == 8`. This is so because of the alignment rules, for our two members we get the following alignment: + +[$images/opt_align1.png] + +This means you can fit twice as many `int`s as `optional`s into the same space of memory. Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type `int` and use some 'magic value' to represent ['not-an-int]. + +Even if you cannot spare any value of `int` to represent ['not-an-int] (e.g., because every value is useful, or you do want to signal ['not-an-int] explicitly), at least for `Trivial` types you should consider storing the value and the `bool` flag representing the ['null-state] separately. Consider the following class: + + struct Record + { + optional _min; + optional _max; + }; + +Its memory layout can be depicted as follows: + +[$images/opt_align2.png] + +This is exactly the same as if we had the following members: + + struct Record + { + bool _has_min; + int _min; + bool _has_max; + int _max; + }; + +But when they are stored separately, we at least have an option to reorder them like this: + + struct Record + { + bool _has_min; + bool _has_max; + int _min; + int _max; + }; + +Which gives us the following layout (and smaller total size): + +[$images/opt_align3.png] + +Sometimes it requires detailed consideration what data we make optional. In our case above, if we determine that both minimum and maximum value can be provided or not provided together, but one is never provided without the other, we can make only one optional memebr: + + struct Limits + { + int _min; + int _max; + }; + + struct Record + { + optional _limits; + }; + +This would give us the following layout: + +[$images/opt_align4.png] + +[heading Optional function parameters] + +Having function parameters of type `const optional&` may incur certain unexpected run-time cost connected to copy construction of `T`. Consider the following code. + + void fun(const optional& v) + { + if (v) doSomethingWith(*v); + else doSomethingElse(); + } + + int main() + { + optional ov; + Big v; + fun(none); + fun(ov); // no copy + fun(v); // copy constructor of Big + } + +No copy elision or move semantics can save us from copying type `Big` here. Not that we need any copy, but this is how `optional` works. In order to avoid copying in this case, one could provide second overload of `fun`: + + void fun(const Big& v) + { + doSomethingWith(v); + } + + int main() + { + optional ov; + Big v; + fun(ov); // no copy + fun(v); // no copy: second overload selected + } + +Alternatively, you could consider using an optional reference instead: + + void fun(optional v) // note where the reference is + { + if (v) doSomethingWith(*v); + else doSomethingElse(); + } + + int main() + { + optional ov; + Big v; + fun(none); + fun(ov); // doesn't compile + fun(v); // no copy + } +[endsect] diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk new file mode 100644 index 0000000..3cffa97 --- /dev/null +++ b/doc/91_relnotes.qbk @@ -0,0 +1,44 @@ +[/ + Boost.Optional + + Copyright (c) 2015 Andrzej Krzemienski + + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +] + + +[section:relnotes Release Notes] + +[heading Boost Release 1.58] + +* `boost::none_t` is no longer convertible from literal `0`. This avoids a bug where `optional> oi = 0;` would initialize an optional object with no contained value. +* Improved the trick that prevents streaming out `optional` without header `optional_io.hpp` by using safe-bool idiom. This addresses [@https://svn.boost.org/trac/boost/ticket/10825 Trac #10825] +* IOStream operators are now mentioned in documentation. +* Added a way to manually disable move semantics: just define macro `BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES`. This can be used to work around [@https://svn.boost.org/trac/boost/ticket/10399 Trac #10399] + + +[heading Boost Release 1.57] + +* [@https://github.com/boostorg/optional/pull/9 Git pull #9]: ['"Supply `` to fix C++03 compile error on `logic_error("...")`"]. + + +[heading Boost Release 1.56] + +* Added support for rvalue references. Now `optional` works with moveable but non-copyable `T`'s, +* Improved `swap` (now uses move operations), +* Added function `emplace()`. This is the last of the requests from [@https://svn.boost.org/trac/boost/ticket/1841 Trac #1841], +* `optional` is moveable, including conditional `noexcept` specifications, which make it `move_if_noexcept`-friendly, +* Using explicit operator bool() on platforms that support it ([@https://svn.boost.org/trac/boost/ticket/4227 Trac #4227]) (breaking change), +* Forward declaration of `operator<<(ostream&, optional const&)` to prevent inadvertent incorrect serialization of optional objects, +* Removed deprecated function `reset()` from examples ([@https://svn.boost.org/trac/boost/ticket/9005 Trac #9005]), +* Equality comparison with `boost::none` does not require that `T` be EqualityComparable, +* Optional rvalue references are explicitly disallowed, +* Binding temporaries to optional references is explicitly disallowed (breaking change), +* More ways to access the contained value, functions `value()`, `value_or()`, `value_or_eval()`, +* Updated and reorganized documentation, added tutorial and quick guide sections. + + + +[endsect][/ relnotes] diff --git a/doc/91_acknowledgments.qbk b/doc/92_acknowledgments.qbk similarity index 98% rename from doc/91_acknowledgments.qbk rename to doc/92_acknowledgments.qbk index cb1b3bb..f337ce2 100644 --- a/doc/91_acknowledgments.qbk +++ b/doc/92_acknowledgments.qbk @@ -9,7 +9,7 @@ ] -[section Acknowledgements] +[section:acknowledgements Acknowledgements] [heading Pre-formal review] diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index debb1b4..fc30664 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -20,6 +20,16 @@ xml optional 00_optional.qbk ; +install images + : + images/opt_align1.png + images/opt_align2.png + images/opt_align3.png + images/opt_align4.png + : + html/images + ; + boostbook standalone : optional diff --git a/doc/html/boost_optional/acknowledgements.html b/doc/html/boost_optional/acknowledgements.html index 659795d..d025d50 100644 --- a/doc/html/boost_optional/acknowledgements.html +++ b/doc/html/boost_optional/acknowledgements.html @@ -6,7 +6,7 @@ - + @@ -19,7 +19,7 @@

-PrevUpHome +PrevUpHome

@@ -116,7 +116,7 @@

-

-PrevUpHome +PrevUpHome
diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html index b99d3b1..06b31e5 100644 --- a/doc/html/boost_optional/dependencies_and_portability.html +++ b/doc/html/boost_optional/dependencies_and_portability.html @@ -75,7 +75,7 @@
-