forked from TartanLlama/optional
Fix #2
This commit is contained in:
71
optional.hpp
71
optional.hpp
@ -337,6 +337,60 @@ template <class T> class optional : private detail::optional_storage_base<T> {
|
|||||||
using base = detail::optional_storage_base<T>;
|
using base = detail::optional_storage_base<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifdef TL_OPTIONAL_CXX14
|
||||||
|
/// \group and_then
|
||||||
|
/// Carries out some operation which returns an optional on the stored object
|
||||||
|
/// if there is one. \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>\nconstexpr auto
|
||||||
|
/// and_then(F &&f) &;
|
||||||
|
template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) & {
|
||||||
|
using result = detail::invoke_result_t<F, T &>;
|
||||||
|
static_assert(detail::is_optional<result>::value,
|
||||||
|
"F must return an optional");
|
||||||
|
|
||||||
|
return has_value() ? detail::invoke(std::forward<F>(f), **this)
|
||||||
|
: result(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \group and_then
|
||||||
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
||||||
|
template <class F> TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && {
|
||||||
|
using result = detail::invoke_result_t<F, T &&>;
|
||||||
|
static_assert(detail::is_optional<result>::value,
|
||||||
|
"F must return an optional");
|
||||||
|
|
||||||
|
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
||||||
|
: result(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \group and_then
|
||||||
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
||||||
|
template <class F> constexpr auto and_then(F &&f) const & {
|
||||||
|
using result = detail::invoke_result_t<F, const T &>;
|
||||||
|
static_assert(detail::is_optional<result>::value,
|
||||||
|
"F must return an optional");
|
||||||
|
|
||||||
|
return has_value() ? detail::invoke(std::forward<F>(f), **this)
|
||||||
|
: result(nullopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
|
/// \group and_then
|
||||||
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||||
|
template <class F> constexpr auto and_then(F &&f) const && {
|
||||||
|
using result = detail::invoke_result_t<F, const T &&>;
|
||||||
|
static_assert(detail::is_optional<result>::value,
|
||||||
|
"F must return an optional");
|
||||||
|
|
||||||
|
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
||||||
|
: result(nullopt);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// Carries out some operation which returns an optional on the stored object
|
/// Carries out some operation which returns an optional on the stored object
|
||||||
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
/// if there is one. \requires `std::invoke(std::forward<F>(f), value())`
|
||||||
@ -347,8 +401,8 @@ public:
|
|||||||
/// is returned. \group and_then \synopsis template <class F>\nconstexpr auto
|
/// is returned. \group and_then \synopsis template <class F>\nconstexpr auto
|
||||||
/// and_then(F &&f) &;
|
/// and_then(F &&f) &;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T> and_then(F &&f) & {
|
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &> and_then(F &&f) & {
|
||||||
using result = detail::invoke_result_t<F, T>;
|
using result = detail::invoke_result_t<F, T &>;
|
||||||
static_assert(detail::is_optional<result>::value,
|
static_assert(detail::is_optional<result>::value,
|
||||||
"F must return an optional");
|
"F must return an optional");
|
||||||
|
|
||||||
@ -359,8 +413,8 @@ public:
|
|||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T> and_then(F &&f) && {
|
TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T &&> and_then(F &&f) && {
|
||||||
using result = detail::invoke_result_t<F, T>;
|
using result = detail::invoke_result_t<F, T &&>;
|
||||||
static_assert(detail::is_optional<result>::value,
|
static_assert(detail::is_optional<result>::value,
|
||||||
"F must return an optional");
|
"F must return an optional");
|
||||||
|
|
||||||
@ -371,8 +425,8 @@ public:
|
|||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr detail::invoke_result_t<F, T> and_then(F &&f) const & {
|
constexpr detail::invoke_result_t<F, const T &> and_then(F &&f) const & {
|
||||||
using result = detail::invoke_result_t<F, T>;
|
using result = detail::invoke_result_t<F, const T &>;
|
||||||
static_assert(detail::is_optional<result>::value,
|
static_assert(detail::is_optional<result>::value,
|
||||||
"F must return an optional");
|
"F must return an optional");
|
||||||
|
|
||||||
@ -384,8 +438,8 @@ public:
|
|||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
constexpr detail::invoke_result_t<F, T> and_then(F &&f) const && {
|
constexpr detail::invoke_result_t<F, const T &&> and_then(F &&f) const && {
|
||||||
using result = detail::invoke_result_t<F, T>;
|
using result = detail::invoke_result_t<F, const T &&>;
|
||||||
static_assert(detail::is_optional<result>::value,
|
static_assert(detail::is_optional<result>::value,
|
||||||
"F must return an optional");
|
"F must return an optional");
|
||||||
|
|
||||||
@ -393,6 +447,7 @@ public:
|
|||||||
: result(nullopt);
|
: result(nullopt);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TL_OPTIONAL_CXX14
|
#ifdef TL_OPTIONAL_CXX14
|
||||||
/// \brief Carries out some operation on the stored object if there is one.
|
/// \brief Carries out some operation on the stored object if there is one.
|
||||||
|
@ -335,11 +335,20 @@ TEST_CASE("Monadic operations", "[monadic]") {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TL_OPTIONAL_CXX14
|
#ifdef TL_OPTIONAL_CXX14
|
||||||
// Reported by Mark Papadakis
|
SECTION("Issue #1") {
|
||||||
SECTION("map const correctness") {
|
|
||||||
tl::optional<foo> f = foo{};
|
tl::optional<foo> f = foo{};
|
||||||
auto l = [](auto &&x) { x.non_const(); };
|
auto l = [](auto &&x) { x.non_const(); };
|
||||||
f.map(l);
|
f.map(l);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct overloaded {
|
||||||
|
tl::optional<int> operator()(foo &) { return 0; }
|
||||||
|
tl::optional<std::string> operator()(const foo &) { return ""; }
|
||||||
|
};
|
||||||
|
|
||||||
|
SECTION("Issue #2") {
|
||||||
|
tl::optional<foo> f = foo{};
|
||||||
|
auto x = f.and_then(overloaded{});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user