diff --git a/doc/27_ref_optional_synopsis.qbk b/doc/27_ref_optional_synopsis.qbk index 8a9386f..2da3b8f 100644 --- a/doc/27_ref_optional_synopsis.qbk +++ b/doc/27_ref_optional_synopsis.qbk @@ -15,6 +15,12 @@ namespace boost { + class in_place_init_t { /* see below */ } ; ``[link reference_in_place_init __GO_TO__]`` + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; ``[link reference_in_place_init_if __GO_TO__]`` + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + template class optional ; ``[link reference_operator_template __GO_TO__]`` @@ -67,6 +73,26 @@ [endsect] +[section:header_optional_in_place_init Initialization tags] + +[#reference_in_place_init] +[#reference_in_place_init_if] + + namespace boost { + + class in_place_init_t { /* see below */ } ; + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + + } + +Classes `in_place_init_t` and `in_place_init_if_t` are empty clsses. Their purpose is to control overload resolution in the initialization of optional objects. +They are empty, trivially copyable classes with disabled default constructor. + +[endsect] + [section:header_optional_optional_values Optional Values] [#reference_operator_template] @@ -91,7 +117,6 @@ optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]`` - // [new in 1.34] optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]`` optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]`` @@ -101,6 +126,10 @@ template explicit optional ( optional const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]`` template explicit optional ( optional&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]`` + + template explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]`` + + template explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]`` template explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]`` diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index e643a9f..1288c56 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -224,6 +224,53 @@ assert( *y == 123 ) ; __SPACE__ +[#reference_optional_in_place_init] + +[: `template explicit optional::optional( in_place_init_t, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] Initializes the contained value as if direct-non-list-initializing an object of type `T` with the +arguments `std::forward(args)...`. +* [*Postconditions:] `*this` is initialized. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +// creates an std::mutex using its default constructor +optional om {in_place_init}; +assert (om); + +// creates a unique_lock by calling unique_lock(*om, std::defer_lock) +optional> ol {in_place_init, *om, std::defer_lock}; +assert (ol); +assert (!ol->owns_lock()); +`` + +__SPACE__ + +[#reference_optional_in_place_init_if] + +[: `template explicit optional::optional( in_place_init_if_t, bool condition, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] If `condition` is `true`, initializes the contained value as if direct-non-list-initializing an object of type `T` with the arguments `std::forward(args)...`. +* [*Postconditions:] `bool(*this) == condition`. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not suppor variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +optional> ov1 {in_place_init_if, false, 3, "A"}; +assert (!ov1); + +optional> ov2 {in_place_init_if, true, 3, "A"}; +assert (ov2); +assert (ov2->size() == 3); +`` + +__SPACE__ + [#reference_optional_constructor_factory] [: `template explicit optional::optional( InPlaceFactory const& f );`] @@ -455,9 +502,7 @@ __SPACE__ * [*Postconditions: ] `*this` is [_initialized]. * [*Throws:] Whatever the selected `T`'s constructor throws. * [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized]. -* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. - On compilers that do not support variadic templates, the signature falls back to two overloads:`template void emplace(Arg&& arg)` and `void emplace()`. - On compilers that do not support rvalue references, the signature falls back to three overloads: taking `const` and non-`const` lvalue reference, and third with empty function argument list. +* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. On compilers that do not suppor variadic templates or rvalue references, this function is available in limited functionality. For details [link optional_emplace_workaround see here]. * [*Example:] `` T v; diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 6d0cccc..b5fa97c 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -27,6 +27,41 @@ The implementation uses the following other Boost modules: [endsect] +[section Emplace operations in older compilers][#optional_emplace_workaround] + +Certain constructors and functions in the interface of `optional` perform a 'perfect forwarding' of arguments: + + template optional(in_place_init_t, Args&&... args); + template optional(in_place_init_if_t, bool condition, Args&&... args); + template void emplace(Args&&... args); + +On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, Arg&& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, Arg&& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(Arg&& arg); + void emplace(); + +On compilers that do not support rvalue references, each of these functions is substituted with three overloadss: taking `const` and non-`const` lvalue reference, and third forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, const Arg& arg); + template optional(in_place_init_t, Arg& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, const Arg& arg); + template optional(in_place_init_if_t, bool condition, Arg& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(const Arg& arg); + template void emplace(Arg& arg); + void emplace(); + +This workaround addressess about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories]. +[endsect] [section Optional Reference Binding][#optional_reference_binding] diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index ef38e5c..a026a8b 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -11,6 +11,10 @@ [section:relnotes Release Notes] +[heading Boost Release 1.63] +* Added two new in-place constructors. They work similarly to `emplace()` functions: they initialize the contained value by perfect-forwarding the obtained arguments. One constructor always initializes the contained value, the other based on a boolean condition. +* Fixed [@https://svn.boost.org/trac/boost/ticket/12203 Trac #12203]. + [heading Boost Release 1.62] diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html index b24c517..ac2309c 100644 --- a/doc/html/boost_optional/dependencies_and_portability.html +++ b/doc/html/boost_optional/dependencies_and_portability.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -29,6 +29,8 @@

@@ -83,7 +85,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html b/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html new file mode 100644 index 0000000..4aedcf7 --- /dev/null +++ b/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html @@ -0,0 +1,90 @@ + + + +Emplace operations in older compilers + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Certain constructors and functions + in the interface of optional + perform a 'perfect forwarding' of arguments: +

+
template<class... Args> optional(in_place_init_t, Args&&... args);
+template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args);
+template<class... Args> void emplace(Args&&... args);
+
+

+ On compilers that do not support variadic templates, each of these functions + is substituted with two overloads, one forwarding a single argument, the + other forwarding zero arguments. This forms the following set: +

+
template<class Arg> optional(in_place_init_t, Arg&& arg);
+optional(in_place_init_t);
+
+template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg);
+optional(in_place_init_if_t, bool condition);
+
+template<class Arg> void emplace(Arg&& arg);
+void emplace();
+
+

+ On compilers that do not support rvalue references, each of these functions + is substituted with three overloadss: taking const + and non-const lvalue reference, + and third forwarding zero arguments. This forms the following set: +

+
template<class Arg> optional(in_place_init_t, const Arg& arg);
+template<class Arg> optional(in_place_init_t, Arg& arg);
+optional(in_place_init_t);
+
+template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg);
+template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg);
+optional(in_place_init_if_t, bool condition);
+
+template<class Arg> void emplace(const Arg& arg);
+template<class Arg> void emplace(Arg& arg);
+void emplace();
+
+

+ This workaround addressess about 40% of all use cases. If this is insufficient, + you need to resort to using In-Place + Factories. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + 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 314bfe6..f38dc20 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 @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
-PrevUpHomeNext +PrevUpHomeNext

@@ -101,7 +101,7 @@
-PrevUpHomeNext +PrevUpHomeNext
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 bd0877a..0d323b5 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 @@ -403,6 +403,94 @@

+

+ space +

+

+ template<class... Args> + explicit optional<T>::optional( in_place_init_t, Args&&... ars + ); +

+
    +
  • + Requires: is_constructible_v<T, Args&&...> is true. +
  • +
  • + Effect: Initializes the contained + value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Any exception thrown by the + selected constructor of T. +
  • +
  • + Notes: T + need not be MoveConstructible. + On compilers that do not suppor variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
  • +
  • + Example: +
    // creates an std::mutex using its default constructor
    +optional<std::mutex> om {in_place_init};
    +assert (om);
    +
    +// creates a unique_lock by calling unique_lock(*om, std::defer_lock)
    +optional<std::unique_lock<std::mutex>> ol {in_place_init, *om, std::defer_lock};
    +assert (ol);
    +assert (!ol->owns_lock());
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + explicit optional<T>::optional( in_place_init_if_t, bool condition, + Args&&... + ars ); +

+
    +
  • + Requires: is_constructible_v<T, Args&&...> is true. +
  • +
  • + Effect: If condition + is true, initializes the + contained value as if direct-non-list-initializing an object of type + T with the arguments + std::forward<Args>(args).... +
  • +
  • + Postconditions: bool(*this) == condition. +
  • +
  • + Throws: Any exception thrown by the + selected constructor of T. +
  • +
  • + Notes: T + need not be MoveConstructible. + On compilers that do not suppor variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
  • +
  • + Example: +
    optional<std::vector<std::string>> ov1 {in_place_init_if, false, 3, "A"};
    +assert (!ov1);
    +
    +optional<std::vector<std::string>> ov2 {in_place_init_if, true, 3, "A"};
    +assert (ov2);
    +assert (ov2->size() == 3);
    +
    +
  • +

space

@@ -1037,15 +1125,8 @@ Notes: T need not be MoveConstructible or MoveAssignable. - On compilers that do not support variadic templates, the signature - falls back to two overloads:template<class - Arg> - void emplace(Arg&& arg) and void - emplace(). - On compilers that do not support rvalue references, the signature falls - back to three overloads: taking const - and non-const lvalue reference, - and third with empty function argument list. + On compilers that do not suppor variadic templates or rvalue references, + this function is available in limited functionality. For details see here.
  • Example: diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html new file mode 100644 index 0000000..8c1a467 --- /dev/null +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html @@ -0,0 +1,61 @@ + + + +Initialization tags + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +
    namespace boost {
    +
    +class in_place_init_t { /* see below */ } ;
    +const in_place_init_t in_place_init ( /* see below */ ) ;
    +
    +class in_place_init_if_t { /*see below*/ } ;
    +const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
    +
    +}
    +
    +

    + Classes in_place_init_t + and in_place_init_if_t + are empty clsses. Their purpose is to control overload resolution in the + initialization of optional objects. They are empty, trivially copyable + classes with disabled default constructor. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + 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 8b5fd70..2d19129 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 @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -47,7 +47,6 @@ optional ( T&& v ) ; R - // [new in 1.34] optional ( bool condition, T const& v ) ; R optional ( optional const& rhs ) ; R @@ -58,6 +57,10 @@ template<class U> explicit optional ( optional<U>&& rhs ) ; R + template<class... Args> explicit optional ( in_place_init_t, Args&&... args ) ; R + + template<class... Args> explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; R + template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R @@ -135,7 +138,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 15b6373..6a6db62 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -28,6 +28,22 @@

    + Boost + Release 1.63 +

    +
      +
    • + Added two new in-place constructors. They work similarly to emplace() + functions: they initialize the contained value by perfect-forwarding the + obtained arguments. One constructor always initializes the contained value, + the other based on a boolean condition. +
    • +
    • + Fixed Trac #12203. +
    • +
    +

    + Boost Release 1.62

    @@ -35,7 +51,7 @@ Fixed Trac #12179.
  • - + Boost Release 1.61

    @@ -78,7 +94,7 @@

    - + Boost Release 1.60

    @@ -89,7 +105,7 @@ #11203.

    - + Boost Release 1.59

    @@ -103,7 +119,7 @@

    - + Boost Release 1.58

    @@ -139,7 +155,7 @@

    - + Boost Release 1.57

    @@ -149,7 +165,7 @@ to fix C++03 compile error on logic_error("...")".

    - + Boost Release 1.56

    diff --git a/doc/html/index.html b/doc/html/index.html index 03e9413..e2a485d 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -89,6 +89,8 @@ and Portability
    Dependencies
    +
    Emplace + operations in older compilers
    Optional Reference Binding
    @@ -143,7 +145,7 @@ - +

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

    Last revised: November 06, 2016 at 00:39:48 GMT


    diff --git a/doc/html/optional/reference/header__boost_optional_optional_hpp_.html b/doc/html/optional/reference/header__boost_optional_optional_hpp_.html index a395d63..c6eec11 100644 --- a/doc/html/optional/reference/header__boost_optional_optional_hpp_.html +++ b/doc/html/optional/reference/header__boost_optional_optional_hpp_.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

    -PrevUpHomeNext +PrevUpHomeNext

    @@ -35,6 +35,12 @@ namespace boost { +class in_place_init_t { /* see below */ } ; R +const in_place_init_t in_place_init ( /* see below */ ) ; + +class in_place_init_if_t { /*see below*/ } ; R +const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + template <class T> class optional ; R @@ -95,7 +101,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index ba3951a..ce55875 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -44,6 +44,23 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +template +struct is_const_integral +{ + static const bool value = boost::is_const::value && boost::is_integral::value; +}; + +template +struct is_const_integral_bad_for_conversion +{ +#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT) + static const bool value = boost::is_const::value && boost::is_integral::value; +#else + static const bool value = false; +#endif +}; + template void prevent_assignment_from_false_const_integral() { @@ -51,12 +68,13 @@ void prevent_assignment_from_false_const_integral() #ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT // MSVC compiler without rvalue refernces: we need to disable the asignment from // const integral lvalue reference, as it may be an invalid temporary - BOOST_STATIC_ASSERT_MSG(!(boost::is_const::value && boost::is_integral::value), + BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, "binding const lvalue references to integral types is disabled in this compiler"); #endif #endif } + template struct is_optional_ { @@ -75,6 +93,21 @@ struct is_no_optional static const bool value = !is_optional_::type>::value; }; + +template + struct is_same_decayed + { + static const bool value = ::boost::is_same::type>::value + || ::boost::is_same::type>::value; + }; + +template +struct no_unboxing_cond +{ + static const bool value = is_no_optional::value && !is_same_decayed::value; +}; + + } // namespace detail template @@ -94,13 +127,21 @@ public: optional(none_t) BOOST_NOEXCEPT : ptr_() {} template - explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} - optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.ptr_) {} + explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} + optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} - - optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } + // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with srewed conversion construction from const int template - optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.ptr_; return *this; } + explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value>::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} + + template + optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value>::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} + + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } + template + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; } @@ -121,8 +162,10 @@ public: #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } + template - optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT + optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } template @@ -154,19 +197,26 @@ public: #else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + // the following two implement a 'conditionally explicit' constructor template - optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } + explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value >::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } + + template + optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value >::type* = 0) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } template - optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} + optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} template - BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type - operator=(U& v) BOOST_NOEXCEPT - { - detail::prevent_assignment_from_false_const_integral(); - ptr_ = boost::addressof(v); return *this; - } + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(U& v) BOOST_NOEXCEPT + { + detail::prevent_assignment_from_false_const_integral(); + ptr_ = boost::addressof(v); return *this; + } template void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if >::type* = 0) BOOST_NOEXCEPT diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index ff1a16c..021588f 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. -// Copyright (C) 2014, 2015 Andrzej Krzemienski. +// Copyright (C) 2014 - 2016 Andrzej Krzemienski. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -56,6 +56,31 @@ #include #else namespace boost { + +namespace optional_ns { + +// a tag for in-place initialization of contained value +struct in_place_init_t +{ + struct init_tag{}; + explicit in_place_init_t(init_tag){} +}; +const in_place_init_t in_place_init ((in_place_init_t::init_tag())); + +// a tag for conditional in-place initialization of contained value +struct in_place_init_if_t +{ + struct init_tag{}; + explicit in_place_init_if_t(init_tag){} +}; +const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag())); + +} // namespace optional_ns + +using optional_ns::in_place_init_t; +using optional_ns::in_place_init; +using optional_ns::in_place_init_if_t; +using optional_ns::in_place_init_if; namespace optional_detail { @@ -338,51 +363,179 @@ class optional_base : public optional_tag #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) // Constructs in-place // upon exception *this is always uninitialized + template + void construct ( in_place_init_t, Args&&... args ) + { + ::new (m_storage.address()) value_type( boost::forward(args)... ) ; + m_initialized = true ; + } + template void emplace_assign ( Args&&... args ) - { - destroy(); - ::new (m_storage.address()) value_type( boost::forward(args)... ); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_t, Args&&... args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(args)...); + } #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template - void emplace_assign ( Arg&& arg ) + void construct ( in_place_init_t, Arg&& arg ) { - destroy(); ::new (m_storage.address()) value_type( boost::forward(arg) ); m_initialized = true ; } - void emplace_assign () + void construct ( in_place_init_t ) { - destroy(); ::new (m_storage.address()) value_type(); m_initialized = true ; } -#else + template - void emplace_assign ( const Arg& arg ) + void emplace_assign ( Arg&& arg ) { destroy(); + construct(in_place_init, boost::forward(arg)) ; + } + + void emplace_assign () + { + destroy(); + construct(in_place_init) ; + } + + template + explicit optional_base ( in_place_init_t, Arg&& arg ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_t ) + : + m_initialized(false) + { + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } + +#else + + template + void construct ( in_place_init_t, const Arg& arg ) + { ::new (m_storage.address()) value_type( arg ); m_initialized = true ; } + template + void construct ( in_place_init_t, Arg& arg ) + { + ::new (m_storage.address()) value_type( arg ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + ::new (m_storage.address()) value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( const Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + template void emplace_assign ( Arg& arg ) - { - destroy(); - ::new (m_storage.address()) value_type( arg ); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init, arg); + } void emplace_assign () - { - destroy(); - ::new (m_storage.address()) value_type(); - m_initialized = true ; - } + { + destroy(); + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_t, const Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_t, Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_t ) + : m_initialized(false) + { + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } #endif #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT @@ -574,7 +727,9 @@ class optional_base : public optional_tag template struct is_optional_related : boost::conditional< boost::is_base_of::type>::value - || boost::is_same::type, none_t>::value, + || boost::is_same::type, none_t>::value + || boost::is_same::type, in_place_init_t>::value + || boost::is_same::type, in_place_init_if_t>::value, boost::true_type, boost::false_type>::type {}; @@ -820,9 +975,20 @@ class optional : public optional_detail::optional_base // upon exception *this is always uninitialized template void emplace ( Args&&... args ) - { - this->emplace_assign( boost::forward(args)... ); - } + { + this->emplace_assign( boost::forward(args)... ); + } + + template + explicit optional ( in_place_init_t, Args&&... args ) + : base( in_place_init, boost::forward(args)... ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) + : base( in_place_init_if, cond, boost::forward(args)... ) + {} + #elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template void emplace ( Arg&& arg ) @@ -834,6 +1000,24 @@ class optional : public optional_detail::optional_base { this->emplace_assign(); } + + template + explicit optional ( in_place_init_t, Args&& args ) + : base( in_place_init, boost::forward(args) ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&& args ) + : base( in_place_init_if, cond, boost::forward(args) ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #else template void emplace ( const Arg& arg ) @@ -851,6 +1035,34 @@ class optional : public optional_detail::optional_base { this->emplace_assign(); } + + template + explicit optional ( in_place_init_t, const Arg& arg ) + : base( in_place_init, arg ) + {} + + template + explicit optional ( in_place_init_t, Arg& arg ) + : base( in_place_init, arg ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} #endif void swap( optional & arg ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7394ce8..ec93e18 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,7 +1,7 @@ # Boost.Optional Library test Jamfile # # Copyright (C) 2003, Fernando Luis Cacciola Carballal. -# Copyright (C) 2014, 2015 Andrzej Krzemienski +# Copyright (C) 2014 - 2016 Andrzej Krzemienski # # Use, modification, and distribution is subject to the Boost Software # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -20,6 +20,7 @@ import testing ; [ run optional_test.cpp ] [ run optional_test_swap.cpp ] [ run optional_test_conversions_from_U.cpp ] + [ run optional_test_convert_from_T.cpp ] [ run optional_test_tie.cpp ] [ run optional_test_ref_assign_portable_minimum.cpp ] [ run optional_test_ref_assign_mutable_int.cpp ] diff --git a/test/optional_test_common.cpp b/test/optional_test_common.cpp index ff197bd..acb935c 100644 --- a/test/optional_test_common.cpp +++ b/test/optional_test_common.cpp @@ -152,21 +152,21 @@ bool X::pending_assign = false ; bool X::throw_on_copy = false ; bool X::throw_on_assign = false ; -inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; } -inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; } -inline void set_pending_assign ( X const* x ) { X::pending_assign = true ; } -inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; } -inline void set_throw_on_assign ( X const* x ) { X::throw_on_assign = true ; } -inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; } -inline void reset_throw_on_assign ( X const* x ) { X::throw_on_assign = false ; } -inline void check_is_pending_copy ( X const* x ) { BOOST_TEST( X::pending_copy ) ; } -inline void check_is_pending_dtor ( X const* x ) { BOOST_TEST( X::pending_dtor ) ; } -inline void check_is_pending_assign ( X const* x ) { BOOST_TEST( X::pending_assign ) ; } -inline void check_is_not_pending_copy ( X const* x ) { BOOST_TEST( !X::pending_copy ) ; } -inline void check_is_not_pending_dtor ( X const* x ) { BOOST_TEST( !X::pending_dtor ) ; } -inline void check_is_not_pending_assign( X const* x ) { BOOST_TEST( !X::pending_assign ) ; } -inline void check_instance_count ( int c, X const* x ) { BOOST_TEST( X::count == c ) ; } -inline int get_instance_count ( X const* x ) { return X::count ; } +inline void set_pending_copy ( X const* ) { X::pending_copy = true ; } +inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; } +inline void set_pending_assign ( X const* ) { X::pending_assign = true ; } +inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; } +inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; } +inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; } +inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; } +inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; } +inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; } +inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; } +inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; } +inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; } +inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; } +inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; } +inline int get_instance_count ( X const* ) { return X::count ; } inline void set_pending_copy (...) {} inline void set_pending_dtor (...) {} diff --git a/test/optional_test_convert_from_T.cpp b/test/optional_test_convert_from_T.cpp new file mode 100644 index 0000000..d4ce4bb --- /dev/null +++ b/test/optional_test_convert_from_T.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; +using boost::none; + +void test_optional_optional_T() +{ + optional oi1 (1), oiN; + optional< optional > ooi1 (oi1), ooiN(oiN); + + BOOST_TEST(ooi1); + BOOST_TEST(*ooi1); + BOOST_TEST_EQ(**ooi1, 1); + + BOOST_TEST(ooiN); + BOOST_TEST(!*ooiN); +} + +int main() +{ + test_optional_optional_T(); + + return boost::report_errors(); +} diff --git a/test/optional_test_emplace.cpp b/test/optional_test_emplace.cpp index 1877a54..36972d3 100644 --- a/test/optional_test_emplace.cpp +++ b/test/optional_test_emplace.cpp @@ -23,6 +23,8 @@ using boost::optional; using boost::none; +using boost::in_place_init; +using boost::in_place_init_if; #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -87,6 +89,109 @@ void test_emplace() BOOST_TEST(7 == o->which_ctor); } +void test_in_place_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init_if, true, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } + + { + optional o (in_place_init_if, false, 1, 2.0); + BOOST_TEST(!o); + } +} + #endif @@ -112,6 +217,24 @@ void test_no_moves_on_emplacement() BOOST_TEST(false); } } + +void test_no_moves_on_in_place_ctor() +{ + try { + optional o (in_place_init, 1); + BOOST_TEST(o); + + optional p (in_place_init_if, true, 1); + BOOST_TEST(p); + + optional q (in_place_init_if, false, 1); + BOOST_TEST(!q); + } + catch (...) { + BOOST_TEST(false); + } +} + #endif struct Thrower @@ -158,6 +281,7 @@ void test_no_assignment_on_emplacement() } namespace no_rvalue_refs { + class Guard { public: @@ -188,19 +312,78 @@ void test_emplace() BOOST_TEST(o); BOOST_TEST(6 == o->which_ctor); } -} + +void test_in_place_ctor() +{ + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + const std::string cs; + std::string ms; + + { + optional n (in_place_init_if, false); + BOOST_TEST(!n); + + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional n (in_place_init_if, false, cs); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional n (in_place_init_if, false, ms); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +} // namespace no_rvalue_ref int main() { #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) test_emplace(); + test_in_place_ctor(); + test_in_place_if_ctor(); #endif #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) test_no_moves_on_emplacement(); + test_no_moves_on_in_place_ctor(); #endif test_clear_on_throw(); test_no_assignment_on_emplacement(); no_rvalue_refs::test_emplace(); + no_rvalue_refs::test_in_place_ctor(); + no_rvalue_refs::test_in_place_if_ctor(); return boost::report_errors(); } diff --git a/test/optional_test_ref_assign_portable_minimum.cpp b/test/optional_test_ref_assign_portable_minimum.cpp index 9ee0a0f..19085d3 100644 --- a/test/optional_test_ref_assign_portable_minimum.cpp +++ b/test/optional_test_ref_assign_portable_minimum.cpp @@ -39,6 +39,7 @@ int main() { test_optional_ref_assignment(); test_optional_ref_assignment(); + test_optional_ref_assignment< optional >(); return boost::report_errors(); } diff --git a/test/optional_test_ref_converting_ctor.cpp b/test/optional_test_ref_converting_ctor.cpp index 735c354..81f3c0f 100644 --- a/test/optional_test_ref_converting_ctor.cpp +++ b/test/optional_test_ref_converting_ctor.cpp @@ -102,6 +102,7 @@ int main() test_all_const_cases(); test_all_const_cases(); test_all_const_cases(); + test_all_const_cases< optional >(); return boost::report_errors(); } diff --git a/test/optional_test_ref_fail_init_from_Trefref.cpp b/test/optional_test_ref_fail_init_from_Trefref.cpp index 05752b8..a08c08a 100644 --- a/test/optional_test_ref_fail_init_from_Trefref.cpp +++ b/test/optional_test_ref_fail_init_from_Trefref.cpp @@ -10,6 +10,7 @@ // akrzemi1@gmail.com // #include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // @@ -18,6 +19,7 @@ void optional_reference__test_no_init_from_Trefref() { boost::optional opt = int(3); + boost::ignore_unused(opt); } #else diff --git a/test/optional_test_ref_fail_init_from_Urefref.cpp b/test/optional_test_ref_fail_init_from_Urefref.cpp index e15192b..af7ca27 100644 --- a/test/optional_test_ref_fail_init_from_Urefref.cpp +++ b/test/optional_test_ref_fail_init_from_Urefref.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014, andrzej Krzemienski. +// Copyright (C) 2014, 2016 andrzej Krzemienski. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -10,6 +10,7 @@ // akrzemi1@gmail.com // #include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // @@ -18,6 +19,7 @@ void optional_reference__test_no_init_from_Urefref() { boost::optional opt = long(3); + boost::ignore_unused(opt); } #else diff --git a/test/optional_test_ref_portable_minimum.cpp b/test/optional_test_ref_portable_minimum.cpp index 5bd7d11..c929c3a 100644 --- a/test/optional_test_ref_portable_minimum.cpp +++ b/test/optional_test_ref_portable_minimum.cpp @@ -430,6 +430,23 @@ void test_swap() BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1)); } +template +void test_convertability_of_compatible_reference_types() +{ + typename concrete_type_of::type v1(1); + optional oN, o1(v1); + optional uN(oN), u1(o1); + BOOST_TEST(!uN); + BOOST_TEST(u1); + BOOST_TEST(boost::addressof(*u1) == boost::addressof(*o1)); + + uN = o1; + u1 = oN; + BOOST_TEST(!u1); + BOOST_TEST(uN); + BOOST_TEST(boost::addressof(*uN) == boost::addressof(*o1)); +} + template void test_optional_ref() { @@ -465,10 +482,18 @@ int main() test_optional_ref(); test_optional_ref(); test_optional_ref(); + test_optional_ref< optional >(); test_optional_const_ref(); test_optional_const_ref(); test_optional_const_ref(); + test_optional_const_ref< optional >(); + + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types(); + test_convertability_of_compatible_reference_types, const optional >(); return boost::report_errors(); } diff --git a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp index 8cc1e70..030b9ba 100644 --- a/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp +++ b/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp @@ -15,7 +15,7 @@ #if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (!defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) -static_assert(false, "failed as requested"); +# error "failed as requested" #else diff --git a/test/testable_classes.hpp b/test/testable_classes.hpp index e18359f..3b2a436 100644 --- a/test/testable_classes.hpp +++ b/test/testable_classes.hpp @@ -12,6 +12,8 @@ #ifndef BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP #define BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP +#include "boost/optional/optional.hpp" + struct ScopeGuard // no copy/move ctor/assign { int val_; @@ -74,13 +76,23 @@ struct has_arrow static const bool value = false; }; +template <> +struct has_arrow< boost::optional > +{ + static const bool value = false; +}; + int& val(int& i) { return i; } int& val(Abstract& a) { return a.val(); } +int& val(Impl& a) { return a.val(); } int& val(ScopeGuard& g) { return g.val(); } +template int& val(T& o) { return *o; } const int& val(const int& i) { return i; } const int& val(const Abstract& a) { return a.val(); } +const int& val(const Impl& a) { return a.val(); } const int& val(const ScopeGuard& g) { return g.val(); } +template const int& val(const T& o) { return *o; } bool operator==(const Abstract& l, const Abstract& r) { return l.val() == r.val(); } bool operator==(const ScopeGuard& l, const ScopeGuard& r) { return l.val() == r.val(); }