mirror of
https://github.com/boostorg/optional.git
synced 2025-07-24 17:47:34 +02:00
value_or() requires that U is convertible to T
Due to Vladimir Batov.
This commit is contained in:
@ -26,8 +26,8 @@ Distributed under the Boost Software License, Version 1.0.
|
|||||||
[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]]
|
[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]]
|
||||||
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
|
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
|
||||||
|
|
||||||
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]]
|
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html `OptionalPointee`]]
|
||||||
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html Copy Constructible]]
|
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html `CopyConstructible`]]
|
||||||
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]]
|
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]]
|
||||||
[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]]
|
[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]]
|
||||||
|
|
||||||
|
@ -908,7 +908,7 @@ __SPACE__
|
|||||||
[: `template<class U> T optional<T>::value_or(U && v) const& ;`]
|
[: `template<class U> T optional<T>::value_or(U && v) const& ;`]
|
||||||
[: `template<class U> T optional<T>::value_or(U && v) && ;`]
|
[: `template<class U> T optional<T>::value_or(U && v) && ;`]
|
||||||
|
|
||||||
* [*Requires:] `T` is CopyConstructible.
|
* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `U &&` is convertible to `T`.
|
||||||
* [*Returns:] First overload: `bool(*this) ? **this : static_cast<T>(forward<U>(v))`. second overload: `bool(*this) ? std::move(**this) : static_cast<T>(forward<U>(v))`.
|
* [*Returns:] First overload: `bool(*this) ? **this : static_cast<T>(forward<U>(v))`. second overload: `bool(*this) ? std::move(**this) : static_cast<T>(forward<U>(v))`.
|
||||||
* [*Throws:] Any exception thrown by the selected constructor of `T`.
|
* [*Throws:] Any exception thrown by the selected constructor of `T`.
|
||||||
* [*Notes:] On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. On compilers without rvalue reference support the type of `v` becomes `U const&`.
|
* [*Notes:] On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. On compilers without rvalue reference support the type of `v` becomes `U const&`.
|
||||||
|
@ -1408,7 +1408,8 @@
|
|||||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||||||
<li class="listitem">
|
<li class="listitem">
|
||||||
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>
|
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>
|
||||||
is CopyConstructible.
|
is <a href="../../../../../utility/CopyConstructible.html" target="_top"><code class="computeroutput"><span class="identifier">CopyConstructible</span></code></a> and <code class="computeroutput"><span class="identifier">U</span> <span class="special">&&</span></code>
|
||||||
|
is convertible to <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||||
</li>
|
</li>
|
||||||
<li class="listitem">
|
<li class="listitem">
|
||||||
<span class="bold"><strong>Returns:</strong></span> First overload: <code class="computeroutput"><span class="keyword">bool</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span> <span class="special">?</span> <span class="special">**</span><span class="keyword">this</span>
|
<span class="bold"><strong>Returns:</strong></span> First overload: <code class="computeroutput"><span class="keyword">bool</span><span class="special">(*</span><span class="keyword">this</span><span class="special">)</span> <span class="special">?</span> <span class="special">**</span><span class="keyword">this</span>
|
||||||
|
@ -98,10 +98,11 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Such a <span class="emphasis"><em>de facto</em></span> idiom for referring to optional objects
|
Such a <span class="emphasis"><em>de facto</em></span> idiom for referring to optional objects
|
||||||
can be formalized in the form of a concept: the <a href="../../../../../../utility/OptionalPointee.html" target="_top">OptionalPointee</a>
|
can be formalized in the form of a concept: the <a href="../../../../../../utility/OptionalPointee.html" target="_top"><code class="computeroutput"><span class="identifier">OptionalPointee</span></code></a> concept. This
|
||||||
concept. This concept captures the syntactic usage of operators <code class="computeroutput"><span class="special">*</span></code>, <code class="computeroutput"><span class="special">-></span></code>
|
concept captures the syntactic usage of operators <code class="computeroutput"><span class="special">*</span></code>,
|
||||||
and contextual conversion to <code class="computeroutput"><span class="keyword">bool</span></code>
|
<code class="computeroutput"><span class="special">-></span></code> and contextual conversion
|
||||||
to convey the notion of optionality.
|
to <code class="computeroutput"><span class="keyword">bool</span></code> to convey the notion
|
||||||
|
of optionality.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
However, pointers are good to <span class="underline">refer</span>
|
However, pointers are good to <span class="underline">refer</span>
|
||||||
@ -127,7 +128,7 @@
|
|||||||
this semantics, so are inappropriate for the initialization and transport
|
this semantics, so are inappropriate for the initialization and transport
|
||||||
of optional values, yet are quite convenient for handling the access to
|
of optional values, yet are quite convenient for handling the access to
|
||||||
the possible undefined value because of the idiomatic aid present in the
|
the possible undefined value because of the idiomatic aid present in the
|
||||||
<a href="../../../../../../utility/OptionalPointee.html" target="_top">OptionalPointee</a>
|
<a href="../../../../../../utility/OptionalPointee.html" target="_top"><code class="computeroutput"><span class="identifier">OptionalPointee</span></code></a>
|
||||||
concept incarnated by pointers.
|
concept incarnated by pointers.
|
||||||
</p>
|
</p>
|
||||||
<h6>
|
<h6>
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
One of the typical problems with wrappers and containers is that their interfaces
|
One of the typical problems with wrappers and containers is that their interfaces
|
||||||
usually provide an operation to initialize or assign the contained object
|
usually provide an operation to initialize or assign the contained object
|
||||||
as a copy of some other object. This not only requires the underlying type
|
as a copy of some other object. This not only requires the underlying type
|
||||||
to be <a href="../../../../../utility/CopyConstructible.html" target="_top">Copy Constructible</a>,
|
to be <a href="../../../../../utility/CopyConstructible.html" target="_top"><code class="computeroutput"><span class="identifier">CopyConstructible</span></code></a>, but also requires
|
||||||
but also requires the existence of a fully constructed object, often temporary,
|
the existence of a fully constructed object, often temporary, just to follow
|
||||||
just to follow the copy from:
|
the copy from:
|
||||||
</p>
|
</p>
|
||||||
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
|
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
|
||||||
<span class="special">{</span>
|
<span class="special">{</span>
|
||||||
|
@ -133,7 +133,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
<td align="left"><p><small>Last revised: June 13, 2014 at 21:36:29 GMT</small></p></td>
|
<td align="left"><p><small>Last revised: June 14, 2014 at 20:46:55 GMT</small></p></td>
|
||||||
<td align="right"><div class="copyright-footer"></div></td>
|
<td align="right"><div class="copyright-footer"></div></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <boost/type_traits/remove_reference.hpp>
|
#include <boost/type_traits/remove_reference.hpp>
|
||||||
#include <boost/type_traits/decay.hpp>
|
#include <boost/type_traits/decay.hpp>
|
||||||
#include <boost/type_traits/is_base_of.hpp>
|
#include <boost/type_traits/is_base_of.hpp>
|
||||||
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
#include <boost/type_traits/is_lvalue_reference.hpp>
|
#include <boost/type_traits/is_lvalue_reference.hpp>
|
||||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||||
@ -1060,18 +1061,31 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
|
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
|
||||||
template <class U>
|
template <class U>
|
||||||
value_type value_or ( U&& v ) const&
|
value_type value_or ( U&& v ) const&
|
||||||
{ return this->is_initialized() ? get() : static_cast<value_type>(boost::forward<U>(v)); }
|
{
|
||||||
|
BOOST_STATIC_ASSERT(is_convertible<U&&, value_type>::value);
|
||||||
|
return this->is_initialized() ? get() : static_cast<value_type>(boost::forward<U>(v));
|
||||||
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
value_type value_or ( U&& v ) &&
|
value_type value_or ( U&& v ) &&
|
||||||
{ return this->is_initialized() ? boost::move(get()) : static_cast<value_type>(boost::forward<U>(v)); }
|
{
|
||||||
|
BOOST_STATIC_ASSERT(is_convertible<U&&, value_type>::value);
|
||||||
|
return this->is_initialized() ? boost::move(get()) : static_cast<value_type>(boost::forward<U>(v));
|
||||||
|
}
|
||||||
#elif !defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
#elif !defined BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||||
template <class U>
|
template <class U>
|
||||||
value_type value_or ( U&& v ) const
|
value_type value_or ( U&& v ) const
|
||||||
{ return this->is_initialized() ? get() : static_cast<value_type>(boost::forward<U>(v)); }
|
{
|
||||||
|
BOOST_STATIC_ASSERT(is_convertible<U&&, value_type>::value);
|
||||||
|
return this->is_initialized() ? get() : static_cast<value_type>(boost::forward<U>(v));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
template <class U>
|
template <class U>
|
||||||
value_type value_or ( U const& v ) const { return this->is_initialized() ? get() : static_cast<value_type>(v); }
|
value_type value_or ( U const& v ) const
|
||||||
|
{
|
||||||
|
BOOST_STATIC_ASSERT(is_convertible<U const&, value_type>::value);
|
||||||
|
return this->is_initialized() ? get() : static_cast<value_type>(v);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
|
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
|
||||||
|
@ -41,5 +41,6 @@ import testing ;
|
|||||||
[ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ]
|
[ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ]
|
||||||
[ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ]
|
[ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ]
|
||||||
[ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ]
|
[ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ]
|
||||||
|
[ compile-fail optional_test_fail_explicit_convert_in_value_or.cpp ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
32
test/optional_test_fail_explicit_convert_in_value_or.cpp
Normal file
32
test/optional_test_fail_explicit_convert_in_value_or.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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.hpp"
|
||||||
|
|
||||||
|
//
|
||||||
|
// THIS TEST SHOULD FAIL TO COMPILE
|
||||||
|
//
|
||||||
|
|
||||||
|
struct U
|
||||||
|
{};
|
||||||
|
|
||||||
|
struct T
|
||||||
|
{
|
||||||
|
explicit T(U const&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void test_implicit_conversion_to_bool()
|
||||||
|
{
|
||||||
|
boost::optional<T> opt;
|
||||||
|
opt.value_or(U());
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user