This commit is contained in:
Simon Brand
2017-10-21 19:41:18 +01:00
parent 8d1a8bc0ac
commit ed27d58e95
2 changed files with 226 additions and 43 deletions

View File

@@ -149,20 +149,58 @@ Represents an empty optional
class optional
{
public:
template <class F> constexpr auto and_then(F &&f);
template <class F> constexpr auto and_then(F &&f) const;
template <class F>
constexpr auto and_then(F &&f) &;
template <class F>
constexpr auto and_then(F &&f) &&;
template <class F>
constexpr auto and_then(F &&f) const &;
template <class F>
constexpr auto and_then(F &&f) const &&;
template <class F> auto map(F &&f);
template <class F> auto map(F &&f) const;
template <class F> auto map(F &&f) &;
template <class F> auto map(F &&f) &&;
template <class F> auto map(F &&f) const &;
template <class F> auto map(F &&f) const &&;
template <class F> optional<T> or_else (F &&f);
template <class F> optional<T> or_else (F &&f) const;
template <class F> optional<T> or_else (F &&f) &;
template <class F> optional<T> or_else (F &&f) &&;
template <class F> optional<T> or_else (F &&f) const &;
template <class F, class U> U map_or(F &&f, U &&u);
template <class F, class U> U map_or(F &&f, U &&u) const;
template <class F, class U>
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;
template &lt;class F, class U&gt; U map_or_else(F &amp;&amp;f, U &amp;&amp;u);
template &lt;class F, class U&gt; U map_or_else(F &amp;&amp;f, U &amp;&amp;u) const;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or_else(F&&,U&&)&'>map_or_else</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or_else(F&&,U&&)&'>map_or_else</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or_else(F&&,U&&)&'>map_or_else</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or_else(F&&,U&&)&'>map_or_else</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;
template &lt;class U&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a> <a href='doc_optional.md#tl::optional-T-::conjunction(U&&)const'>conjunction</a>(U&amp;&amp; u) const;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;&amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &amp;&amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &amp;&amp;;
using <a href='doc_optional.md#tl::optional-T-'>value_type</a> = T;
@@ -228,9 +266,17 @@ An optional object is an object that contains the storage for another object and
### Function template `tl::optional::and_then`<a id="tl::optional-T-::and_then(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt; constexpr auto and_then(F &amp;&amp;f);
<pre><code class="language-cpp">(1) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt; constexpr auto and_then(F &amp;&amp;f) const;</code></pre>
(2) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;;
(4) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;&amp;;</code></pre>
Carries out some operation which returns an optional on the stored object if there is one.
@@ -240,9 +286,13 @@ Carries out some operation which returns an optional on the stored object if the
### Function template `tl::optional::map`<a id="tl::optional-T-::map(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt; auto map(F &amp;&amp;f);
<pre><code class="language-cpp">(1) template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt; auto map(F &amp;&amp;f) const;</code></pre>
(2) template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;;
(4) template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;&amp;;</code></pre>
Carries out some operation on the stored object if there is one.
@@ -250,9 +300,11 @@ Carries out some operation on the stored object if there is one.
### Function template `tl::optional::or_else`<a id="tl::optional-T-::or_else(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f);
<pre><code class="language-cpp">(1) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) const;</code></pre>
(2) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) const &amp;;</code></pre>
Calls `f` if the optional is empty
@@ -262,9 +314,17 @@ Calls `f` if the optional is empty
### Function template `tl::optional::map_or`<a id="tl::optional-T-::map_or(F&&,U&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt; U map_or(F &amp;&amp;f, U &amp;&amp;u);
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) &amp;;
(2) template &lt;class F, class U&gt; U map_or(F &amp;&amp;f, U &amp;&amp;u) const;</code></pre>
(2) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
(3) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
(4) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;</code></pre>
Maps the stored value with `f` if there is one, otherwise returns `u`
@@ -272,14 +332,61 @@ If there is a value stored, then `f` is called with `**this` and the value is re
### Function template `tl::optional::map_or_else`<a id="tl::optional-T-::map_or_else(F&&,U&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt; U map_or_else(F &amp;&amp;f, U &amp;&amp;u);
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt;
U map_or_else(F&amp;&amp; f, U&amp;&amp; u) &amp;;
(2) template &lt;class F, class U&gt; U map_or_else(F &amp;&amp;f, U &amp;&amp;u) const;</code></pre>
(2) template &lt;class F, class U&gt;
U map_or_else(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
(3) template &lt;class F, class U&gt;
U map_or_else(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
(4) template &lt;class F, class U&gt;
U map_or_else(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;</code></pre>
Maps the stored value with `f` if there is one, otherwise calls `u` and returns the result.
If there is a value stored, then `f` is called with `**this` and the value is returned. Otherwise `std::forward<U>(u)()` is returned.
### Function template `tl::optional::conjunction`<a id="tl::optional-T-::conjunction(U&&)const"></a>
<pre><code class="language-cpp">template &lt;class U&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a> conjunction(U&amp;&amp; u) const;</code></pre>
*Returns*: `u` if `*this` has a value, otherwise an empty optional.
### Function `tl::optional::disjunction`<a id="tl::optional-T-::disjunction(constoptional-T-&)&"></a>
<pre><code class="language-cpp">(1) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;;
(2) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;;
(3) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;&amp;;
(4) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;&amp;;
(5) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;;
(6) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;;
(7) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;&amp;;
(8) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;&amp;;</code></pre>
*Returns*: `rhs` if `*this` is empty, otherwise the current value.
### Function `tl::optional::take`<a id="tl::optional-T-::take()&"></a>
<pre><code class="language-cpp">(1) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() &amp;;
(2) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &amp;;
(3) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() &amp;&amp;;
(4) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &amp;&amp;;</code></pre>
Takes the value out of the optional, leaving it empty
### Default constructor `tl::optional::optional`<a id="tl::optional-T-::optional()"></a>
<pre><code class="language-cpp">(1) constexpr optional() noexcept = default;
@@ -335,7 +442,7 @@ Converting move constructor.
<pre><code class="language-cpp">~optional() = default;</code></pre>
Destructor.
Destroys the stored value if there is one.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(tl::nullopt_t)"></a>

View File

@@ -361,7 +361,7 @@ public:
/// \requires `std::invoke(std::forward<F>(f), value())` returns a `std::optional<U>` for some `U`.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), value())`. Returns a `std::optional<U>`. The return value is empty if `*this` is empty, otherwise the return value of `std::invoke(std::forward<F>(f), value())` is returned.
/// \group and_then
/// \synopsis template <class F> constexpr auto and_then(F &&f);
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &;
template <class F>
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T> and_then(F &&f) & {
using result = detail::invoke_result_t<F, T>;
@@ -372,7 +372,8 @@ public:
: result(nullopt);
}
/// \exclude
/// \group and_then
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
template <class F>
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T> and_then(F &&f) && {
using result = detail::invoke_result_t<F, T>;
@@ -384,7 +385,7 @@ public:
}
/// \group and_then
/// \synopsis template <class F> constexpr auto and_then(F &&f) const;
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
template <class F>
constexpr detail::invoke_result_t<F, T> and_then(F &&f) const & {
using result = detail::invoke_result_t<F, T>;
@@ -395,7 +396,8 @@ public:
: result(nullopt);
}
/// \exclude
/// \group and_then
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
template <class F>
constexpr detail::invoke_result_t<F, T> and_then(F &&f) const && {
using result = detail::invoke_result_t<F, T>;
@@ -409,7 +411,7 @@ public:
/// \brief Carries out some operation on the stored object if there is one.
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), value())`. Returns a `std::optional<U>`. The return value is empty if `*this` is empty, otherwise an `optional<U>` is constructed from the return value of `std::invoke(std::forward<F>(f), value())` and is returned.
/// \group map
/// \synopsis template <class F> auto map(F &&f);
/// \synopsis template <class F> auto map(F &&f) &;
template <class F, detail::disable_if_optional<F> * = nullptr,
detail::disable_if_ret_void<F, T &> * = nullptr>
detail::get_map_return<F, T &> map(F &&f) &
@@ -452,7 +454,8 @@ public:
return monostate{};
}
/// \exclude
/// \group map
/// \synopsis template <class F> auto map(F &&f) &&;
template <class F, detail::disable_if_optional<F> * = nullptr,
detail::disable_if_ret_void<F, T &&> * = nullptr>
detail::get_map_return<F, T &&> map(F &&f) && {
@@ -494,7 +497,7 @@ public:
}
/// \group map
/// \synopsis template <class F> auto map(F &&f) const;
/// \synopsis template <class F> auto map(F &&f) const &;
template <class F, detail::disable_if_optional<F> * = nullptr,
detail::disable_if_ret_void<F, T const &> * = nullptr>
constexpr detail::get_map_return<F, T const &> map(F &&f) const & {
@@ -536,7 +539,8 @@ public:
return monostate{};
}
/// \exclude
/// \group map
/// \synopsis template <class F> auto map(F &&f) const &&;
template <class F, detail::disable_if_optional<F> * = nullptr,
detail::disable_if_ret_void<F, T const &&> * = nullptr>
constexpr detail::get_map_return<F, T const &&> map(F &&f) const && {
@@ -581,7 +585,7 @@ public:
/// \requires `std::invoke_result_t<F>` must be void or convertible to `optional<T>`.
/// \effects If `*this` has a value, returns `*this`. Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
/// \group or_else
/// \synopsis template <class F> optional<T> or_else (F &&f);
/// \synopsis template <class F> optional<T> or_else (F &&f) &;
template <class F, detail::enable_if_ret_void<F> * = nullptr>
optional<T> TL_OPTIONAL_MSVC_2015_CONSTEXPR or_else(F &&f) & {
if (has_value())
@@ -597,7 +601,8 @@ public:
return has_value() ? *this : std::forward<F>(f)();
}
/// \exclude
/// \group or_else
/// \synopsis template <class F> optional<T> or_else (F &&f) &&;
template <class F, detail::enable_if_ret_void<F> * = nullptr>
optional<T> or_else(F &&f) && {
if (has_value())
@@ -613,7 +618,8 @@ public:
return has_value() ? std::move(*this) : std::forward<F>(f)();
}
/// \exclude
/// \group or_else
/// \synopsis template <class F> optional<T> or_else (F &&f) const &;
template <class F, detail::enable_if_ret_void<F> * = nullptr>
optional<T> or_else(F &&f) const & {
if (has_value())
@@ -623,8 +629,7 @@ public:
return nullopt;
}
/// \group or_else
/// \synopsis template <class F> optional<T> or_else (F &&f) const;
/// \exclude
template <class F, detail::disable_if_ret_void<F> * = nullptr>
optional<T> TL_OPTIONAL_MSVC_2015_CONSTEXPR or_else(F &&f) const & {
return has_value() ? *this : std::forward<F>(f)();
@@ -651,26 +656,24 @@ public:
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
/// Otherwise `u` is returned.
/// \group map_or
/// \synopsis template <class F, class U> U map_or(F &&f, U &&u);
template <class F, class U> U map_or(F &&f, U &&u) & {
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: std::forward<U>(u);
}
/// \exclude
/// \group map_or
template <class F, class U> U map_or(F &&f, U &&u) && {
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
: std::forward<U>(u);
}
/// \group map_or
/// \synopsis template <class F, class U> U map_or(F &&f, U &&u) const;
template <class F, class U> U map_or(F &&f, U &&u) const & {
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: std::forward<U>(u);
}
/// \exclude
/// \group map_or
template <class F, class U> U map_or(F &&f, U &&u) const && {
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
: std::forward<U>(u);
@@ -679,32 +682,105 @@ public:
/// \brief Maps the stored value with `f` if there is one, otherwise calls `u` and returns the result.
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
/// Otherwise `std::forward<U>(u)()` is returned.
/// \synopsis template <class F, class U> U map_or_else(F &&f, U &&u);
/// \group map_or_else
template <class F, class U> U map_or_else(F &&f, U &&u) & {
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: std::forward<U>(u)();
}
/// \exclude
/// \group map_or_else
template <class F, class U> U map_or_else(F &&f, U &&u) && {
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
: std::forward<U>(u)();
}
/// \group map_or_else
/// \synopsis template <class F, class U> U map_or_else(F &&f, U &&u) const;
template <class F, class U> U map_or_else(F &&f, U &&u) const & {
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: std::forward<U>(u)();
}
/// \exclude
/// \group map_or_else
template <class F, class U> U map_or_else(F &&f, U &&u) const && {
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
: std::forward<U>(u)();
}
/// \returns `u` if `*this` has a value, otherwise an empty optional.
template <class U> constexpr optional<U> conjunction (U &&u) const {
return has_value() ? u : nullopt;
}
/// \returns `rhs` if `*this` is empty, otherwise the current value.
/// \group disjunction
constexpr optional disjunction (const optional &rhs) & {
return has_value() ? *this : rhs;
}
/// \group disjunction
constexpr optional disjunction (const optional &rhs) const & {
return has_value() ? *this : rhs;
}
/// \group disjunction
constexpr optional disjunction (const optional &rhs) && {
return has_value() ? std::move(*this) : rhs;
}
/// \group disjunction
constexpr optional disjunction (const optional &rhs) const && {
return has_value() ? std::move(*this) : rhs;
}
/// \group disjunction
constexpr optional disjunction (optional &&rhs) & {
return has_value() ? *this : std::move(rhs);
}
/// \group disjunction
constexpr optional disjunction (optional &&rhs) const & {
return has_value() ? *this : std::move(rhs);
}
/// \group disjunction
constexpr optional disjunction (optional &&rhs) && {
return has_value() ? std::move(*this) : std::move(rhs);
}
/// \group disjunction
constexpr optional disjunction (optional &&rhs) const && {
return has_value() ? std::move(*this) : std::move(rhs);
}
/// Takes the value out of the optional, leaving it empty
/// \group take
optional take() & {
optional ret = *this;
reset();
return ret;
}
/// \group take
optional take() const & {
optional ret = *this;
reset();
return ret;
}
/// \group take
optional take() && {
optional ret = std::move(*this);
reset();
return ret;
}
/// \group take
optional take() const && {
optional ret = std::move(*this);
reset();
return ret;
}
using value_type = T;
/// Constructs an optional that does not contain a value.
@@ -813,7 +889,7 @@ public:
new (std::addressof(this->m_value)) T(std::move(*rhs));
}
/// Destructor.
/// Destroys the stored value if there is one.
~optional() = default;
/// Assignment to empty.