diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index 14f4d4a..e6ebc4c 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -83,7 +83,7 @@ This is how you solve it with `boost::optional`: [include 14_io.qbk] [include 15_optional_references.qbk] [include 16_in_place_factories.qbk] -[include 17_optional_bool.qbk] +[include 17_gotchas.qbk] [include 18_exception_safety.qbk] [include 19_type_requirements.qbk] [include 1A_on_performance.qbk] diff --git a/doc/17_gotchas.qbk b/doc/17_gotchas.qbk new file mode 100644 index 0000000..743c5bf --- /dev/null +++ b/doc/17_gotchas.qbk @@ -0,0 +1,111 @@ +[section Gotchas] + +[section A note about optional] + +`optional` should be used with special caution and consideration. + +First, it is functionally similar to a tristate boolean (false, maybe, true) +—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state +[_represents a valid value], unlike the corresponding state of an uninitialized +`optional`. +It should be carefully considered if an `optional` instead of a `tribool` +is really needed. + +Second, although `optional<>` provides a contextual conversion to `bool` in C++11, + this falls back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using `optional` + can lead to subtle errors due to the implicit `bool` conversion: + + void foo ( bool v ) ; + void bar() + { + optional v = try(); + + // The following intended to pass the value of 'v' to foo(): + foo(v); + // But instead, the initialization state is passed + // due to a typo: it should have been foo(*v). + } + +The only implicit conversion is to `bool`, and it is safe in the sense that +typical integral promotions don't apply (i.e. if `foo()` takes an `int` +instead, it won't compile). + +Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: + + optional oEmpty(none), oTrue(true), oFalse(false); + + if (oEmpty == none); // renders true + if (oEmpty == false); // renders false! + if (oEmpty == true); // renders false! + + if (oFalse == none); // renders false + if (oFalse == false); // renders true! + if (oFalse == true); // renders false + + if (oTrue == none); // renders false + if (oTrue == false); // renders false + if (oTrue == true); // renders true + +In other words, for `optional<>`, the following assertion does not hold: + + assert((opt == false) == (!opt)); +[endsect] + +[section Moved-from `optional`] + +When an optional object that contains a value is moved from (is a source of move constructor or assignment) it still contains a value and its contained value is left in a moved-from state. This can be illustrated with the following example. + + optional> opi {std::make_unique(1)}; + optional> opj = std::move(opi); + assert (opi); + assert (*opi == nullptr); + +Quite a lot of people expect that when an object that contains a value is moved from, its contained value should be destroyed. This is not so, for performance reasons. Current semantics allow the implementation of `boost::opiotnal` to be trivially copyable when `T` is trivial. +[endsect] + +[section Mixed relational comparisons] + +Because `T` is convertible to `optional` and because `opiotnal` is __SGI_LESS_THAN_COMPARABLE__ when `T` is __SGI_LESS_THAN_COMPARABLE__, +you can sometimes get an unexpected runtime result where you would rather expect a compiler error: + + optional Flight_plan::weight(); // sometimes no weight can be returned + + bool is_aircraft_too_heavy(Flight_plan const& p) + { + return p.weight() > p.aircraft().max_weight(); // compiles! + } // returns false when the optional contains no value + +[endsect] + +[section False positive with -Wmaybe-uninitialized] + +Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized warning when copiling with option -02 on a perfectly valid `boost::optional` usage. For instance in this program: + + #include + + boost::optional getitem(); + + int main(int argc, const char *[]) + { + boost::optional a = getitem(); + boost::optional b; + + if (argc > 0) + b = argc; + + if (a != b) + return 1; + + return 0; + } + +This is a bug in the compiler. As a workaround (provided in [@http://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct this Stack Overflow question]) use the following way of initializing an optional containing no value: + + boost::optional b = std::make_optional(false, int()); + +This is obviously redundant, but makes the warning disappear. + +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/17_optional_bool.qbk b/doc/17_optional_bool.qbk deleted file mode 100644 index 6f3664f..0000000 --- a/doc/17_optional_bool.qbk +++ /dev/null @@ -1,52 +0,0 @@ - -[section A note about optional] - -`optional` should be used with special caution and consideration. - -First, it is functionally similar to a tristate boolean (false, maybe, true) -—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state -[_represents a valid value], unlike the corresponding state of an uninitialized -`optional`. -It should be carefully considered if an `optional` instead of a `tribool` -is really needed. - -Second, although `optional<>` provides a contextual conversion to `bool` in C++11, - this falls back to an implicit conversion on older compilers. This conversion refers - to the initialization state and not to the contained value. Using `optional` - can lead to subtle errors due to the implicit `bool` conversion: - - void foo ( bool v ) ; - void bar() - { - optional v = try(); - - // The following intended to pass the value of 'v' to foo(): - foo(v); - // But instead, the initialization state is passed - // due to a typo: it should have been foo(*v). - } - -The only implicit conversion is to `bool`, and it is safe in the sense that -typical integral promotions don't apply (i.e. if `foo()` takes an `int` -instead, it won't compile). - -Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: - - optional oEmpty(none), oTrue(true), oFalse(false); - - if (oEmpty == none); // renders true - if (oEmpty == false); // renders false! - if (oEmpty == true); // renders false! - - if (oFalse == none); // renders false - if (oFalse == false); // renders true! - if (oFalse == true); // renders false - - if (oTrue == none); // renders false - if (oTrue == false); // renders false - if (oTrue == true); // renders true - -In other words, for `optional<>`, the following assertion does not hold: - - assert((opt == false) == (!opt)); -[endsect] diff --git a/doc/1A_on_performance.qbk b/doc/1A_on_performance.qbk index 841190f..5fd749a 100644 --- a/doc/1A_on_performance.qbk +++ b/doc/1A_on_performance.qbk @@ -23,7 +23,7 @@ Given type `optional`, and assuming that `sizeof(int) == 4`, we will get `s [$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]. +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], or use something like [@https://github.com/akrzemi1/markable `markable`] library. 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: diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index 803b244..e643a9f 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -770,6 +770,7 @@ __SPACE__ [: `template optional::optional(R&& r) noexcept;`] * [*Postconditions:] `bool(*this) == true`; `addressof(**this) == addressof(r)`. * [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. +* [*Notes:] This constructor is declared `explicit` on compilers that do not correctly suport binding to const lvalues of integral types. For more details [link optional_reference_binding see here]. * [*Example:] `` T v; diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 80e1803..6d0cccc 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -28,7 +28,7 @@ The implementation uses the following other Boost modules: [endsect] -[section Optional Reference Binding] +[section Optional Reference Binding][#optional_reference_binding] A number of compilers incorrectly treat const lvalues of integral type as rvalues, and create an illegal temporary when binding to an lvalue reference to const in some expressions. This could result in creating an optional lvalue reference that is in fact bound to an unexpected temporary rather than to the intended object. In order to prevent hard to find run-time bugs, this library performs compile-time checks to prevent expressions that would otherwise bind an optional reference to an unexpected temporary. As a consequence, on certain compilers certain pieces of functionality in optional references are missing. In order to maintain a portability of your code across diferent compilers, it is recommended that you only stick to the minimum portable interface of optional references: prefer direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`: diff --git a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html index fbe4ba8..314bfe6 100644 --- a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html +++ b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html @@ -28,18 +28,19 @@ Reference Binding

- A number of compilers incorrectly treat const lvalues of integral type as - rvalues, and create an illegal temporary when binding to an lvalue reference - to const in some expressions. This could result in creating an optional lvalue - reference that is in fact bound to an unexpected temporary rather than to - the intended object. In order to prevent hard to find run-time bugs, this - library performs compile-time checks to prevent expressions that would otherwise - bind an optional reference to an unexpected temporary. As a consequence, - on certain compilers certain pieces of functionality in optional references - are missing. In order to maintain a portability of your code across diferent - compilers, it is recommended that you only stick to the minimum portable - interface of optional references: prefer direct-initialization and copy assignment - of optional references to copy-initialization and assignment from T&: + A number of compilers incorrectly + treat const lvalues of integral type as rvalues, and create an illegal temporary + when binding to an lvalue reference to const in some expressions. This could + result in creating an optional lvalue reference that is in fact bound to + an unexpected temporary rather than to the intended object. In order to prevent + hard to find run-time bugs, this library performs compile-time checks to + prevent expressions that would otherwise bind an optional reference to an + unexpected temporary. As a consequence, on certain compilers certain pieces + of functionality in optional references are missing. In order to maintain + a portability of your code across diferent compilers, it is recommended that + you only stick to the minimum portable interface of optional references: + prefer direct-initialization and copy assignment of optional references to + copy-initialization and assignment from T&:

const int i = 0;
 optional<const int&> or1;
diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
index f786277..4b33196 100644
--- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
+++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html
@@ -268,9 +268,7 @@
             optional<T> const& x ) noexcept;
           

  • - Returns: !( - x == - y ); + Returns: bool(x);

space diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html index 0bca093..71b01dd 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html @@ -55,6 +55,12 @@ is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if decay<R> is an instance of boost::optional. +

  • + Notes: This constructor is declared + explicit on compilers + that do not correctly suport binding to const lvalues of integral types. + For more details see here. +
  • Example:
    T v;
    diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    index a33ad48..bd0877a 100644
    --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html
    @@ -1007,7 +1007,7 @@
             

    template<class... Args> - void optional<T>::emplace( Args...&& args + void optional<T>::emplace( Args&&... args );

      diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html index 56d02de..8b5fd70 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html @@ -76,7 +76,7 @@ template<class U> optional& operator = ( optional<U>&& rhs ) ; R - template<class... Args> void emplace ( Args...&& args ) ; R + template<class... Args> void emplace ( Args&&... args ) ; R template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R diff --git a/doc/html/boost_optional/tutorial/exception_safety_guarantees.html b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html index edce61d..cfabeea 100644 --- a/doc/html/boost_optional/tutorial/exception_safety_guarantees.html +++ b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
      -PrevUpHomeNext +PrevUpHomeNext

      @@ -169,7 +169,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/tutorial/gotchas.html b/doc/html/boost_optional/tutorial/gotchas.html new file mode 100644 index 0000000..790aa19 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas.html @@ -0,0 +1,112 @@ + + + +Gotchas + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +
      + +

      + optional<bool> + should be used with special caution and consideration. +

      +

      + First, it is functionally similar to a tristate boolean (false, maybe, + true) —such as boost::tribool— + except that in a tristate boolean, the maybe state represents + a valid value, unlike the corresponding state of an uninitialized + optional<bool>. + It should be carefully considered if an optional<bool> instead of a tribool + is really needed. +

      +

      + Second, although optional<> provides a contextual conversion + to bool in C++11, this falls + back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using optional<bool> + can lead to subtle errors due to the implicit bool + conversion: +

      +
      void foo ( bool v ) ;
      +void bar()
      +{
      +    optional<bool> v = try();
      +
      +    // The following intended to pass the value of 'v' to foo():
      +    foo(v);
      +    // But instead, the initialization state is passed
      +    // due to a typo: it should have been foo(*v).
      +}
      +
      +

      + The only implicit conversion is to bool, + and it is safe in the sense that typical integral promotions don't apply + (i.e. if foo() + takes an int instead, it won't + compile). +

      +

      + Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

      +
      optional<bool> oEmpty(none), oTrue(true), oFalse(false);
      +
      +if (oEmpty == none);  // renders true
      +if (oEmpty == false); // renders false!
      +if (oEmpty == true);  // renders false!
      +
      +if (oFalse == none);  // renders false
      +if (oFalse == false); // renders true!
      +if (oFalse == true);  // renders false
      +
      +if (oTrue == none);   // renders false
      +if (oTrue == false);  // renders false
      +if (oTrue == true);   // renders true
      +
      +

      + In other words, for optional<>, the following assertion does not + hold: +

      +
      assert((opt == false) == (!opt));
      +
      +
      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html b/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html new file mode 100644 index 0000000..1ecc562 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html @@ -0,0 +1,77 @@ + + + +False positive with -Wmaybe-uninitialized + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized + warning when copiling with option -02 on a perfectly valid boost::optional usage. For instance in this + program: +

      +
      #include <boost/optional.hpp>
      +
      +boost::optional<int> getitem();
      +
      +int main(int argc, const char *[])
      +{
      +  boost::optional<int> a = getitem();
      +  boost::optional<int> b;
      +
      +  if (argc > 0)
      +    b = argc;
      +
      +  if (a != b)
      +    return 1;
      +
      +  return 0;
      +}
      +
      +

      + This is a bug in the compiler. As a workaround (provided in this + Stack Overflow question) use the following way of initializing + an optional containing no value: +

      +
      boost::optional<int> b = std::make_optional(false, int());
      +
      +

      + This is obviously redundant, but makes the warning disappear. +

      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html b/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html new file mode 100644 index 0000000..b4391f7 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html @@ -0,0 +1,59 @@ + + + +Mixed relational comparisons + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + Because T is convertible + to optional<T> + and because opiotnal<T> + is LessThanComparable when T is LessThanComparable, you can sometimes + get an unexpected runtime result where you would rather expect a compiler + error: +

      +
      optional<double> Flight_plan::weight(); // sometimes no weight can be returned
      +
      +bool is_aircraft_too_heavy(Flight_plan const& p)
      +{
      +   return p.weight() > p.aircraft().max_weight(); // compiles!
      +}                                                 // returns false when the optional contains no value 
      +
      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html b/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html new file mode 100644 index 0000000..faecd74 --- /dev/null +++ b/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html @@ -0,0 +1,63 @@ + + + +Moved-from optional + + + + + + + + + + + + + + + +
      Boost C++ LibrariesHomeLibrariesPeopleFAQMore
      +
      +
      +PrevUpHomeNext +
      +
      + +

      + When an optional object that contains a value is moved from (is a source + of move constructor or assignment) it still contains a value and its contained + value is left in a moved-from state. This can be illustrated with the following + example. +

      +
      optional<std::unique_ptr<int>> opi {std::make_unique<int>(1)};
      +optional<std::unique_ptr<int>> opj = std::move(opi);
      +assert (opi);
      +assert (*opi == nullptr);
      +
      +

      + Quite a lot of people expect that when an object that contains a value + is moved from, its contained value should be destroyed. This is not so, + for performance reasons. Current semantics allow the implementation of + boost::opiotnal<T> + to be trivially copyable when T + is trivial. +

      +
      + + + +
      +
      +
      +PrevUpHomeNext +
      + + diff --git a/doc/html/boost_optional/tutorial/in_place_factories.html b/doc/html/boost_optional/tutorial/in_place_factories.html index 3b72041..3895f2e 100644 --- a/doc/html/boost_optional/tutorial/in_place_factories.html +++ b/doc/html/boost_optional/tutorial/in_place_factories.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

      -PrevUpHomeNext +PrevUpHomeNext

      @@ -191,7 +191,7 @@
      -PrevUpHomeNext +PrevUpHomeNext
      diff --git a/doc/html/boost_optional/tutorial/performance_considerations.html b/doc/html/boost_optional/tutorial/performance_considerations.html index db70539..0f999e9 100644 --- a/doc/html/boost_optional/tutorial/performance_considerations.html +++ b/doc/html/boost_optional/tutorial/performance_considerations.html @@ -67,7 +67,7 @@ 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. + not-an-int, or use something like markable library.

      Even if you cannot spare any value of int diff --git a/doc/html/index.html b/doc/html/index.html index 74f80df..03e9413 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -64,8 +64,7 @@ references

      In-Place Factories
      -
      A - note about optional<bool>
      +
      Gotchas
      Exception Safety Guarantees
      Type requirements
      @@ -144,7 +143,7 @@

      - +

      Last revised: September 02, 2016 at 00:05:57 GMT

      Last revised: September 16, 2016 at 23:43:36 GMT


      diff --git a/doc/html/optional/tutorial.html b/doc/html/optional/tutorial.html index 556944d..9ae3774 100644 --- a/doc/html/optional/tutorial.html +++ b/doc/html/optional/tutorial.html @@ -38,8 +38,7 @@ references
      In-Place Factories
      -
      A - note about optional<bool>
      +
      Gotchas
      Exception Safety Guarantees
      Type requirements