[/
    Boost.Optional

    Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal

    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 Dependencies and Portability][#minimum_system_requirements]


[section Minimum System Requirements]
This library requires C++11 as minimum. However, in C++11 some features are disabled.

[section:constexpr Support for `constexpr`]

[section C++11]
For compilers fully supporting C++11 (including unconstrained unions and ref-qualifiers),
for trivially-destructible `T`s, `optional<T>` is a ['literal type] and its constructors
with `this->has_value() == false` as postcondition:

* `optional()`,
* `optional(none_t)`,

are ['core constant expressions]. Even for other `T`s, these constructors are guaranteed to
perform ['constant initialization]: they are never subject to "initialization order fiasco".

Other constructors with `this->has_value() == true`
as postcondition are core constant expressions if the expression required to initialize
the contained value is a core constant expression. This includes constructors:

* `template <typename... Args> optional(in_place_init, Args&&...)`,
* `template <typename U> optional(U&&)`,
* `optional(const T&)`,
* `optional(T&&)`.

Other constructors, including the copy and move constructos, are ['not] core constant expressions.

Member functions `.has_value`, `operator bool` and (non)equality comparisons with `none` are core-constant expressions for trivially-destructible `T`s.

Also all `const`-qualified non-static member functions and comparison operators are core constant expressions, if the corresponding operations on `T`
are core constant expressions.
[endsect]

[section C++14]
For C++14 and higher this library, for trivially-destructible `T`s provides the `constexpr` interface for all mutable and non-mutable
member functions, as long as:

* the corresponding operations on `T` are core constant expressions and
* the member never attempts to change the `optional`'s state from not containing a value to containing a value.

[note For types that overload unary `operator&` (address) some member functions in `optional`, like `operator->`,
cannot be implemented as `constexpr` on some compilers.]
[endsect]

[section C++17]
In C++17 all non-deprecated constructors are core constant expressions as long as
`T` is a literal type and its constructor used is a core constant expression.
[endsect]

[endsect:constexpr]

[endsect]


[section Dependencies]
The implementation uses the following other Boost modules:

# assert
# config
# core
# throw_exception
# type_traits

[endsect]


[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 different 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;
    optional<const int&> or2 = i;  // caution: not portable
    or1 = i;                       // caution: not portable

    optional<const int&> or3(i);   // portable
    or1 = optional<const int&>(i); // portable

Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.

    #include <cassert>

    const int global_i = 0;

    struct TestingReferenceBinding
    {
      TestingReferenceBinding(const int& ii)
      {
        assert(&ii == &global_i);
      }

      void operator=(const int& ii)
      {
        assert(&ii == &global_i);
      }

      void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
      {
        assert(false);
      }
    };

    int main()
    {
      const int& iref = global_i;
      assert(&iref == &global_i);

      TestingReferenceBinding ttt = global_i;
      ttt = global_i;

      TestingReferenceBinding ttt2 = iref;
      ttt2 = iref;
    }

[endsect]

[endsect]
