mirror of
https://github.com/boostorg/optional.git
synced 2025-07-22 16:47:15 +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_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
|
||||
|
||||
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]]
|
||||
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html Copy Constructible]]
|
||||
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html `OptionalPointee`]]
|
||||
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html `CopyConstructible`]]
|
||||
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_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) && ;`]
|
||||
|
||||
* [*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))`.
|
||||
* [*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&`.
|
||||
|
@ -1408,7 +1408,8 @@
|
||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||||
<li class="listitem">
|
||||
<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 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>
|
||||
|
@ -98,10 +98,11 @@
|
||||
</p>
|
||||
<p>
|
||||
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>
|
||||
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>
|
||||
and contextual conversion to <code class="computeroutput"><span class="keyword">bool</span></code>
|
||||
to convey the notion of optionality.
|
||||
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 captures the syntactic usage of operators <code class="computeroutput"><span class="special">*</span></code>,
|
||||
<code class="computeroutput"><span class="special">-></span></code> and contextual conversion
|
||||
to <code class="computeroutput"><span class="keyword">bool</span></code> to convey the notion
|
||||
of optionality.
|
||||
</p>
|
||||
<p>
|
||||
However, pointers are good to <span class="underline">refer</span>
|
||||
@ -127,7 +128,7 @@
|
||||
this semantics, so are inappropriate for the initialization and transport
|
||||
of optional values, yet are quite convenient for handling the access to
|
||||
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.
|
||||
</p>
|
||||
<h6>
|
||||
|
@ -31,9 +31,9 @@
|
||||
One of the typical problems with wrappers and containers is that their interfaces
|
||||
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
|
||||
to be <a href="../../../../../utility/CopyConstructible.html" target="_top">Copy Constructible</a>,
|
||||
but also requires the existence of a fully constructed object, often temporary,
|
||||
just to follow the copy from:
|
||||
to be <a href="../../../../../utility/CopyConstructible.html" target="_top"><code class="computeroutput"><span class="identifier">CopyConstructible</span></code></a>, but also requires
|
||||
the existence of a fully constructed object, often temporary, just to follow
|
||||
the copy from:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
|
||||
<span class="special">{</span>
|
||||
|
@ -133,7 +133,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</tr></table>
|
||||
<hr>
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/decay.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_nothrow_move_assignable.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
|
||||
template <class U>
|
||||
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>
|
||||
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
|
||||
template <class U>
|
||||
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
|
||||
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
|
||||
|
||||
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_assign_from_Trefref.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