value_or() requires that U is convertible to T

Due to Vladimir Batov.
This commit is contained in:
Andrzej Krzemienski
2014-06-14 22:49:37 +02:00
parent 8fc2901fad
commit 31c9119266
9 changed files with 66 additions and 17 deletions

View File

@ -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()`]]

View File

@ -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&`.

View File

@ -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">&amp;&amp;</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>

View File

@ -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">-&gt;</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">-&gt;</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>

View File

@ -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>

View File

@ -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>

View File

@ -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() ; }

View File

@ -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 ]
;
}

View 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());
}