util: update bundled copy of optional-lite

This updates optional.hpp to upstream git commit
063af3ed2e830f3fcb77c635c6391e5d65c51fe5

Change-Id: Ie390b2818fa4dff8c600b777b77104b7f0c11f9d
diff --git a/src/util/nonstd/optional.hpp b/src/util/nonstd/optional.hpp
index b460791..764598a 100644
--- a/src/util/nonstd/optional.hpp
+++ b/src/util/nonstd/optional.hpp
@@ -3,7 +3,7 @@
 //
 // https://github.com/martinmoene/optional-lite
 //
-// Distributed under the Boost Software License, Version 1.0. 
+// Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
 #pragma once
@@ -11,34 +11,63 @@
 #ifndef NONSTD_OPTIONAL_LITE_HPP
 #define NONSTD_OPTIONAL_LITE_HPP
 
-#define  optional_lite_VERSION "3.0.0"
+#define optional_lite_MAJOR  3
+#define optional_lite_MINOR  1
+#define optional_lite_PATCH  0
 
-// Compiler detection (C++20 is speculative):
-// Note: MSVC supports C++14 since it supports C++17.
+#define optional_lite_VERSION  optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY(optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
 
-#ifdef _MSVC_LANG
-# define optional_MSVC_LANG  _MSVC_LANG
-#else
-# define optional_MSVC_LANG  0
+#define optional_STRINGIFY(  x )  optional_STRINGIFY_( x )
+#define optional_STRINGIFY_( x )  #x
+
+// optional-lite configuration:
+
+#define optional_OPTIONAL_DEFAULT  0
+#define optional_OPTIONAL_NONSTD   1
+#define optional_OPTIONAL_STD      2
+
+#if !defined( optional_CONFIG_SELECT_OPTIONAL )
+# define optional_CONFIG_SELECT_OPTIONAL  ( optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD : optional_OPTIONAL_NONSTD )
 #endif
 
-#define optional_CPP11             (__cplusplus == 201103L )
-#define optional_CPP11_OR_GREATER  (__cplusplus >= 201103L || optional_MSVC_LANG >= 201103L )
-#define optional_CPP14_OR_GREATER  (__cplusplus >= 201402L || optional_MSVC_LANG >= 201703L )
-#define optional_CPP17_OR_GREATER  (__cplusplus >= 201703L || optional_MSVC_LANG >= 201703L )
-#define optional_CPP20_OR_GREATER  (__cplusplus >= 202000L || optional_MSVC_LANG >= 202000L )
+// C++ language version detection (C++20 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
 
-// use C++17 std::optional if available:
-
-#if defined( __has_include )
-# define optional_HAS_INCLUDE( arg )  __has_include( arg )
-#else
-# define optional_HAS_INCLUDE( arg )  0
+#ifndef   optional_CPLUSPLUS
+# ifdef  _MSVC_LANG
+#  define optional_CPLUSPLUS  (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+#  define optional_CPLUSPLUS  __cplusplus
+# endif
 #endif
 
-#define optional_HAVE_STD_OPTIONAL  ( optional_CPP17_OR_GREATER && optional_HAS_INCLUDE( <optional> ) )
+#define optional_CPP98_OR_GREATER  ( optional_CPLUSPLUS >= 199711L )
+#define optional_CPP11_OR_GREATER  ( optional_CPLUSPLUS >= 201103L )
+#define optional_CPP14_OR_GREATER  ( optional_CPLUSPLUS >= 201402L )
+#define optional_CPP17_OR_GREATER  ( optional_CPLUSPLUS >= 201703L )
+#define optional_CPP20_OR_GREATER  ( optional_CPLUSPLUS >= 202000L )
 
-#if optional_HAVE_STD_OPTIONAL
+// C++ language version (represent 98 as 3):
+
+#define optional_CPLUSPLUS_V  ( optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994) )
+
+// Use C++17 std::optional if available and requested:
+
+#if optional_CPP17_OR_GREATER && defined(__has_include )
+# if __has_include( <optional> )
+#  define optional_HAVE_STD_OPTIONAL  1
+# else
+#  define optional_HAVE_STD_OPTIONAL  0
+# endif
+#else
+# define  optional_HAVE_STD_OPTIONAL  0
+#endif
+
+#define optional_USES_STD_OPTIONAL  ( (optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && optional_HAVE_STD_OPTIONAL) )
+
+// Using std::optional:
+
+#if optional_USES_STD_OPTIONAL
 
 #include <optional>
 
@@ -67,7 +96,7 @@
     using std::swap;
 }
 
-#else // C++17 std::optional
+#else // optional_USES_STD_OPTIONAL
 
 #include <cassert>
 #include <stdexcept>
@@ -89,10 +118,10 @@
 
 // Compiler warning suppression:
 
-#ifdef __clang__
+#if defined (__clang__)
 # pragma clang diagnostic push
 # pragma clang diagnostic ignored "-Wundef"
-#elif defined __GNUC__
+#elif defined (__GNUC__)
 # pragma GCC   diagnostic push
 # pragma GCC   diagnostic ignored "-Wundef"
 #endif
@@ -108,13 +137,13 @@
 
 #define optional_COMPILER_VERSION( major, minor, patch )  ( 10 * (10 * major + minor ) + patch )
 
-#if defined __GNUC__
+#if defined (__GNUC__) && !defined(__clang__)
 # define optional_COMPILER_GNUC_VERSION   optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
 #else
 # define optional_COMPILER_GNUC_VERSION   0
 #endif
 
-#if defined __clang__
+#if defined (__clang__)
 # define optional_COMPILER_CLANG_VERSION  optional_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
 #else
 # define optional_COMPILER_CLANG_VERSION  0
@@ -259,27 +288,54 @@
 # include <tr1/type_traits>
 #endif
 
-// type traits needed:
+// Method enabling
 
-namespace nonstd { namespace optional_lite { namespace detail {
+#if optional_CPP11_OR_GREATER
 
-#if optional_HAVE( CONDITIONAL )
-    using std::conditional;
-#else
-    template< bool B, typename T, typename F > struct conditional              { typedef T type; };
-    template<         typename T, typename F > struct conditional<false, T, F> { typedef F type; };
-#endif // optional_HAVE_CONDITIONAL
+# define optional_REQUIRES_T(...) \
+    , typename = typename std::enable_if<__VA_ARGS__>::type
 
-}}}
+# define optional_REQUIRES_R(R, ...) \
+    typename std::enable_if<__VA_ARGS__, R>::type
+
+# define optional_REQUIRES_A(...) \
+    , typename std::enable_if<__VA_ARGS__, void*>::type = optional_nullptr
+
+#endif
 
 //
-// in_place: code duplicated in any-lite, optional-lite, variant-lite:
+// in_place: code duplicated in any-lite, expected-lite, optional-lite, variant-lite:
 //
 
 #ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
+#define nonstd_lite_HAVE_IN_PLACE_TYPES  1
+
+// C++17 std::in_place in <utility>:
+
+#if optional_CPP17_OR_GREATER
 
 namespace nonstd {
 
+using std::in_place;
+using std::in_place_type;
+using std::in_place_index;
+using std::in_place_t;
+using std::in_place_type_t;
+using std::in_place_index_t;
+
+#define nonstd_lite_in_place_t(      T)  std::in_place_t
+#define nonstd_lite_in_place_type_t( T)  std::in_place_type_t<T>
+#define nonstd_lite_in_place_index_t(T)  std::in_place_index_t<I>
+
+#define nonstd_lite_in_place(      T)    std::in_place_t{}
+#define nonstd_lite_in_place_type( T)    std::in_place_type_t<T>{}
+#define nonstd_lite_in_place_index(T)    std::in_place_index_t<I>{}
+
+} // namespace nonstd
+
+#else // optional_CPP17_OR_GREATER
+
+namespace nonstd {
 namespace detail {
 
 template< class T >
@@ -318,13 +374,17 @@
 
 // mimic templated typedef:
 
+#define nonstd_lite_in_place_t(      T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
 #define nonstd_lite_in_place_type_t( T)  nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T>  )
 #define nonstd_lite_in_place_index_t(T)  nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<I> )
 
-#define nonstd_lite_HAVE_IN_PLACE_TYPES  1
+#define nonstd_lite_in_place(      T)    nonstd::in_place_type<T>
+#define nonstd_lite_in_place_type( T)    nonstd::in_place_type<T>
+#define nonstd_lite_in_place_index(T)    nonstd::in_place_index<I>
 
 } // namespace nonstd
 
+#endif // optional_CPP17_OR_GREATER
 #endif // nonstd_lite_HAVE_IN_PLACE_TYPES
 
 //
@@ -333,6 +393,33 @@
 
 namespace nonstd { namespace optional_lite {
 
+namespace detail {
+
+#if optional_HAVE( CONDITIONAL )
+    using std::conditional;
+#else
+    template< bool B, typename T, typename F > struct conditional              { typedef T type; };
+    template<         typename T, typename F > struct conditional<false, T, F> { typedef F type; };
+#endif // optional_HAVE_CONDITIONAL
+
+} // namespace detail
+
+#if optional_CPP11_OR_GREATER
+
+namespace std20 {
+
+// type traits C++20:
+
+template< typename T >
+struct remove_cvref
+{
+    typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
+};
+
+} // namespace std20
+
+#endif // optional_CPP11_OR_GREATER
+
 /// class optional
 
 template< typename T >
@@ -418,10 +505,10 @@
 #define optional_ALIGN_AS( to_align ) \
     typename type_of_size< alignment_types, alignment_of< to_align >::value >::type
 
-template <typename T>
+template< typename T >
 struct alignment_of;
 
-template <typename T>
+template< typename T >
 struct alignment_of_hack
 {
     char c;
@@ -429,7 +516,7 @@
     alignment_of_hack();
 };
 
-template <unsigned A, unsigned S>
+template< size_t A, size_t S >
 struct alignment_logic
 {
     enum { value = A < S ? A : S };
@@ -439,7 +526,7 @@
 struct alignment_of
 {
     enum { value = alignment_logic<
-        sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value, };
+        sizeof( alignment_of_hack<T> ) - sizeof(T), sizeof(T) >::value };
 };
 
 template< typename List, size_t N >
@@ -501,8 +588,8 @@
 template< typename T >
 union storage_t
 {
-private:
-    friend class optional<T>;
+//private:
+//    template< typename > friend class optional;
 
     typedef T value_type;
 
@@ -573,12 +660,12 @@
 
     value_type const && value() const optional_refref_qual
     {
-        return * value_ptr();
+        return std::move( value() );
     }
 
     value_type && value() optional_refref_qual
     {
-        return * value_ptr();
+        return std::move( value() );
     }
 
 #endif
@@ -660,140 +747,396 @@
 class optional
 {
 private:
+    template< typename > friend class optional;
+
     typedef void (optional::*safe_bool)() const;
 
 public:
     typedef T value_type;
 
+    // x.x.3.1, constructors
+
+    // 1a - default construct
     optional_constexpr optional() optional_noexcept
     : has_value_( false )
     , contained()
     {}
 
+    // 1b - construct explicitly empty
     optional_constexpr optional( nullopt_t ) optional_noexcept
     : has_value_( false )
     , contained()
     {}
 
-    optional( optional const & rhs )
-    : has_value_( rhs.has_value() )
-    {
-        if ( rhs.has_value() )
-            contained.construct_value( rhs.contained.value() );
-    }
-
+    // 2 - copy-construct
+    optional_constexpr14 optional( optional const & other
 #if optional_CPP11_OR_GREATER
-    optional_constexpr14 optional( optional && rhs ) noexcept( std::is_nothrow_move_constructible<T>::value )
-    : has_value_( rhs.has_value() )
-    {
-        if ( rhs.has_value() )
-            contained.construct_value( std::move( rhs.contained.value() ) );
-    }
+        optional_REQUIRES_A(
+            true || std::is_copy_constructible<T>::value
+        )
 #endif
-
-    optional_constexpr optional( value_type const & value )
-    : has_value_( true )
-    , contained( value )
-    {}
+    )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( other.contained.value() );
+    }
 
 #if optional_CPP11_OR_GREATER
 
-    optional_constexpr optional( value_type && value )
-    : has_value_( true )
-    , contained( std::move( value ) )
-    {}
+    // 3 (C++11) - move-construct from optional
+    optional_constexpr14 optional( optional && other
+        optional_REQUIRES_A(
+            true || std::is_move_constructible<T>::value
+        )
+    ) noexcept( std::is_nothrow_move_constructible<T>::value )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( std::move( other.contained.value() ) );
+    }
 
-    template< class... Args >
-    optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), Args&&... args )
+    // 4 (C++11) - explicit converting copy-construct from optional
+    template< typename U >
+    explicit optional( optional<U> const & other
+        optional_REQUIRES_A(
+            std::is_constructible<T, U const &>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            && !std::is_convertible<               U const & , T>::value /*=> explicit */
+        )
+    )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( other.contained.value() );
+    }
+#endif // optional_CPP11_OR_GREATER
+
+    // 4 (C++98 and later) - non-explicit converting copy-construct from optional
+    template< typename U >
+    optional( optional<U> const & other
+#if optional_CPP11_OR_GREATER
+        optional_REQUIRES_A(
+            std::is_constructible<T, U const &>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            &&  std::is_convertible<               U const & , T>::value /*=> non-explicit */
+        )
+#endif // optional_CPP11_OR_GREATER
+    )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( other.contained.value() );
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    // 5a (C++11) - explicit converting move-construct from optional
+    template< typename U >
+    optional( optional<U> && other
+        optional_REQUIRES_A(
+            std::is_constructible<T, U const &>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            && !std::is_convertible<                     U &&, T>::value /*=> explicit */
+        )
+    )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( std::move( other.contained.value() ) );
+    }
+
+    // 5a (C++11) - non-explicit converting move-construct from optional
+    template< typename U >
+    optional( optional<U> && other
+        optional_REQUIRES_A(
+            std::is_constructible<T, U const &>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            &&  std::is_convertible<                     U &&, T>::value /*=> non-explicit */
+        )
+    )
+    : has_value_( other.has_value() )
+    {
+        if ( other.has_value() )
+            contained.construct_value( std::move( other.contained.value() ) );
+    }
+
+    // 6 (C++11) - in-place construct
+    template< typename... Args
+        optional_REQUIRES_T(
+            std::is_constructible<T, Args&&...>::value
+        )
+    >
+    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), Args&&... args )
     : has_value_( true )
     , contained( T( std::forward<Args>(args)...) )
     {}
 
-    template< class U, class... Args >
-    optional_constexpr explicit optional( nonstd_lite_in_place_type_t(T), std::initializer_list<U> il, Args&&... args )
+    // 7 (C++11) - in-place construct,  initializer-list
+    template< typename U, typename... Args
+        optional_REQUIRES_T(
+            std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
+        )
+    >
+    optional_constexpr explicit optional( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
     : has_value_( true )
     , contained( T( il, std::forward<Args>(args)...) )
     {}
 
+    // 8a (C++11) - explicit move construct from value
+    template< typename U = value_type >
+    optional_constexpr explicit optional( U && value
+        optional_REQUIRES_A(
+            std::is_constructible<T, U&&>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+            && !std::is_convertible<U&&, T>::value /*=> explicit */
+        )
+    )
+    : has_value_( true )
+    , contained( std::forward<U>( value ) )
+    {}
+
+    // 8a (C++11) - non-explicit move construct from value
+    template< typename U = value_type >
+    optional_constexpr optional( U && value
+        optional_REQUIRES_A(
+            std::is_constructible<T, U&&>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+            && std::is_convertible<U&&, T>::value /*=> non-explicit */
+        )
+    )
+    : has_value_( true )
+    , contained( std::forward<U>( value ) )
+    {}
+
+#else // optional_CPP11_OR_GREATER
+
+    // 8 (C++98)
+    optional( value_type const & value )
+    : has_value_( true )
+    , contained( value )
+    {}
+
 #endif // optional_CPP11_OR_GREATER
 
+    // x.x.3.2, destructor
+
     ~optional()
     {
         if ( has_value() )
             contained.destruct_value();
     }
 
-    // assignment
+    // x.x.3.3, assignment
 
+    // 1 (C++98and later) -  assign explicitly empty
     optional & operator=( nullopt_t ) optional_noexcept
     {
         reset();
         return *this;
     }
 
-    optional & operator=( optional const & rhs )
+    // 2 (C++98and later) - copy-assign from optional
 #if optional_CPP11_OR_GREATER
-        noexcept( std::is_nothrow_move_assignable<T>::value && std::is_nothrow_move_constructible<T>::value )
+    optional_REQUIRES_R(
+        optional &,
+        true
+//      std::is_copy_constructible<T>::value
+//      && std::is_copy_assignable<T>::value
+    )
+    operator=( optional const & other )
+        noexcept(
+            std::is_nothrow_move_assignable<T>::value
+            && std::is_nothrow_move_constructible<T>::value
+        )
+#else
+    optional & operator=( optional const & other )
 #endif
     {
-        if      ( has_value() == true  && rhs.has_value() == false ) reset();
-        else if ( has_value() == false && rhs.has_value() == true  ) initialize( *rhs );
-        else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = *rhs;
+        if      ( has_value() == true  && other.has_value() == false ) reset();
+        else if ( has_value() == false && other.has_value() == true  ) initialize( *other );
+        else if ( has_value() == true  && other.has_value() == true  ) contained.value() = *other;
         return *this;
     }
 
 #if optional_CPP11_OR_GREATER
 
-    optional & operator=( optional && rhs ) noexcept
+    // 3 (C++11) - move-assign from optional
+    optional_REQUIRES_R(
+        optional &,
+        true
+//      std::is_move_constructible<T>::value
+//      && std::is_move_assignable<T>::value
+    )
+    operator=( optional && other ) noexcept
     {
-        if      ( has_value() == true  && rhs.has_value() == false ) reset();
-        else if ( has_value() == false && rhs.has_value() == true  ) initialize( std::move( *rhs ) );
-        else if ( has_value() == true  && rhs.has_value() == true  ) contained.value() = std::move( *rhs );
+        if      ( has_value() == true  && other.has_value() == false ) reset();
+        else if ( has_value() == false && other.has_value() == true  ) initialize( std::move( *other ) );
+        else if ( has_value() == true  && other.has_value() == true  ) contained.value() = std::move( *other );
         return *this;
     }
 
-    template< class U,
-        typename = typename std::enable_if< std::is_same< typename std::decay<U>::type, T>::value >::type >
-    optional & operator=( U && v )
+    // 4 (C++11) - move-assign from value
+    template< typename U = T >
+        optional_REQUIRES_R(
+            optional &,
+            std::is_constructible<T , U>::value
+            && std::is_assignable<T&, U>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+            && !std::is_same<typename std20::remove_cvref<U>::type, optional<T>>::value
+//          && !(std::is_scalar<T>::value && std::is_same<T, typename std::decay<U>::type>::value)
+        )
+    operator=( U && value )
     {
-        if ( has_value() ) contained.value() = std::forward<U>( v );
-        else               initialize( T( std::forward<U>( v ) ) );
+        if ( has_value() ) contained.value() = std::forward<U>( value );
+        else               initialize( T( std::forward<U>( value ) ) );
         return *this;
     }
 
-    template< class... Args >
-    void emplace( Args&&... args )
-    {
-        *this = nullopt;
-        contained.emplace( std::forward<Args>(args)...  );
-        has_value_ = true;
-    }
+#else // optional_CPP11_OR_GREATER
 
-
-    template< class U, class... Args >
-    void emplace( std::initializer_list<U> il, Args&&... args )
+    // 4 (C++98) - copy-assign from value
+    template< typename U /*= T*/ >
+    optional & operator=( U const & value )
     {
-        *this = nullopt;
-        contained.emplace( il, std::forward<Args>(args)...  );
-        has_value_ = true;
+        if ( has_value() ) contained.value() = value;
+        else               initialize( T( value ) );
+        return *this;
     }
 
 #endif // optional_CPP11_OR_GREATER
 
-    // swap
-
-    void swap( optional & rhs )
+    // 5 (C++98 and later) - converting copy-assign from optional
+    template< typename U >
 #if optional_CPP11_OR_GREATER
-    noexcept( std::is_nothrow_move_constructible<T>::value && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) ) )
+        optional_REQUIRES_R(
+            optional&,
+            std::is_constructible<  T , U const &>::value
+            &&  std::is_assignable< T&, U const &>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            && !std::is_assignable<  T&, optional<U> &          >::value
+            && !std::is_assignable<  T&, optional<U> &&         >::value
+            && !std::is_assignable<  T&, optional<U> const &    >::value
+            && !std::is_assignable<  T&, optional<U> const &&   >::value
+        )
+#else
+    optional&
+#endif // optional_CPP11_OR_GREATER
+    operator=( optional<U> const & other )
+    {
+        return *this = optional( other );
+    }
+
+#if optional_CPP11_OR_GREATER
+
+    // 6 (C++11) -  converting move-assign from optional
+    template< typename U >
+        optional_REQUIRES_R(
+            optional&,
+            std::is_constructible<  T , U>::value
+            &&  std::is_assignable< T&, U>::value
+            && !std::is_constructible<T, optional<U> &          >::value
+            && !std::is_constructible<T, optional<U> &&         >::value
+            && !std::is_constructible<T, optional<U> const &    >::value
+            && !std::is_constructible<T, optional<U> const &&   >::value
+            && !std::is_convertible<     optional<U> &       , T>::value
+            && !std::is_convertible<     optional<U> &&      , T>::value
+            && !std::is_convertible<     optional<U> const & , T>::value
+            && !std::is_convertible<     optional<U> const &&, T>::value
+            && !std::is_assignable<  T&, optional<U> &          >::value
+            && !std::is_assignable<  T&, optional<U> &&         >::value
+            && !std::is_assignable<  T&, optional<U> const &    >::value
+            && !std::is_assignable<  T&, optional<U> const &&   >::value
+        )
+    operator=( optional<U> && other )
+    {
+        return *this = optional( std::move( other ) );
+    }
+
+    // 7 (C++11) - emplace
+    template< typename... Args
+        optional_REQUIRES_T(
+            std::is_constructible<T, Args&&...>::value
+        )
+    >
+    T& emplace( Args&&... args )
+    {
+        *this = nullopt;
+        contained.emplace( std::forward<Args>(args)...  );
+        has_value_ = true;
+        return contained.value();
+    }
+
+    // 8 (C++11) - emplace, initializer-list
+    template< typename U, typename... Args
+        optional_REQUIRES_T(
+            std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value
+        )
+    >
+    T& emplace( std::initializer_list<U> il, Args&&... args )
+    {
+        *this = nullopt;
+        contained.emplace( il, std::forward<Args>(args)...  );
+        has_value_ = true;
+        return contained.value();
+    }
+
+#endif // optional_CPP11_OR_GREATER
+
+    // x.x.3.4, swap
+
+    void swap( optional & other )
+#if optional_CPP11_OR_GREATER
+        noexcept(
+            std::is_nothrow_move_constructible<T>::value
+            && noexcept( std::swap( std::declval<T&>(), std::declval<T&>() ) )
+        )
 #endif
     {
         using std::swap;
-        if      ( has_value() == true  && rhs.has_value() == true  ) { swap( **this, *rhs ); }
-        else if ( has_value() == false && rhs.has_value() == true  ) { initialize( *rhs ); rhs.reset(); }
-        else if ( has_value() == true  && rhs.has_value() == false ) { rhs.initialize( **this ); reset(); }
+        if      ( has_value() == true  && other.has_value() == true  ) { swap( **this, *other ); }
+        else if ( has_value() == false && other.has_value() == true  ) { initialize( *other ); other.reset(); }
+        else if ( has_value() == true  && other.has_value() == false ) { other.initialize( **this ); reset(); }
     }
 
-    // observers
+    // x.x.3.5, observers
 
     optional_constexpr value_type const * operator ->() const
     {
@@ -823,14 +1166,12 @@
 
     optional_constexpr value_type const && operator *() const optional_refref_qual
     {
-        return assert( has_value() ),
-            std::move( contained.value() );
+        return std::move( **this );
     }
 
     optional_constexpr14 value_type && operator *() optional_refref_qual
     {
-        return assert( has_value() ),
-            std::move( contained.value() );
+        return std::move( **this );
     }
 
 #endif
@@ -872,31 +1213,25 @@
 
     optional_constexpr14 value_type const && value() const optional_refref_qual
     {
-        if ( ! has_value() )
-            throw bad_optional_access();
-
-        return std::move( contained.value() );
+        return std::move( value() );
     }
 
     optional_constexpr14 value_type && value() optional_refref_qual
     {
-        if ( ! has_value() )
-            throw bad_optional_access();
-
-        return std::move( contained.value() );
+        return std::move( value() );
     }
 
 #endif
 
 #if optional_CPP11_OR_GREATER
 
-    template< class U >
+    template< typename U >
     optional_constexpr value_type value_or( U && v ) const optional_ref_qual
     {
         return has_value() ? contained.value() : static_cast<T>(std::forward<U>( v ) );
     }
 
-    template< class U >
+    template< typename U >
     optional_constexpr value_type value_or( U && v ) const optional_refref_qual
     {
         return has_value() ? std::move( contained.value() ) : static_cast<T>(std::forward<U>( v ) );
@@ -904,7 +1239,7 @@
 
 #else
 
-    template< class U >
+    template< typename U >
     optional_constexpr value_type value_or( U const & v ) const
     {
         return has_value() ? contained.value() : static_cast<value_type>( v );
@@ -912,7 +1247,7 @@
 
 #endif // optional_CPP11_OR_GREATER
 
-    // modifiers
+    // x.x.3.6, modifiers
 
     void reset() optional_noexcept
     {
@@ -1149,35 +1484,35 @@
 
 #if optional_CPP11_OR_GREATER
 
-template< class T >
-optional_constexpr optional< typename std::decay<T>::type > make_optional( T && v )
+template< typename T >
+optional_constexpr optional< typename std::decay<T>::type > make_optional( T && value )
 {
-    return optional< typename std::decay<T>::type >( std::forward<T>( v ) );
+    return optional< typename std::decay<T>::type >( std::forward<T>( value ) );
 }
 
-template< class T, class...Args >
+template< typename T, typename...Args >
 optional_constexpr optional<T> make_optional( Args&&... args )
 {
-    return optional<T>( in_place, std::forward<Args>(args)...);
+    return optional<T>( nonstd_lite_in_place(T), std::forward<Args>(args)...);
 }
 
-template< class T, class U, class... Args >
+template< typename T, typename U, typename... Args >
 optional_constexpr optional<T> make_optional( std::initializer_list<U> il, Args&&... args )
 {
-    return optional<T>( in_place, il, std::forward<Args>(args)...);
+    return optional<T>( nonstd_lite_in_place(T), il, std::forward<Args>(args)...);
 }
 
 #else
 
 template< typename T >
-optional<T> make_optional( T const & v )
+optional<T> make_optional( T const & value )
 {
-    return optional<T>( v );
+    return optional<T>( value );
 }
 
 #endif // optional_CPP11_OR_GREATER
 
-} // namespace optional
+} // namespace optional_lite
 
 using namespace optional_lite;
 
@@ -1203,12 +1538,12 @@
 
 #endif // optional_CPP11_OR_GREATER
 
-#ifdef __clang__
+#if defined (__clang__)
 # pragma clang diagnostic pop
-#elif defined __GNUC__
+#elif defined (__GNUC__)
 # pragma GCC   diagnostic pop
 #endif
 
-#endif // have C++17 std::optional
+#endif // optional_USES_STD_OPTIONAL
 
 #endif // NONSTD_OPTIONAL_LITE_HPP