'optional<T&>::and_then(F&& f) &&' calls f with lvalue reference

This makes sense. The 'optional' is an rvalue, but its contained type
remains an lvalue reference. I.e.

int i = 3;
optional<int&>{i}.and_then([](int& r){return optional<int&>{++r});

The optional r-value still refers to 'i', which is not an r-value.
This commit is contained in:
Bj?rn Fahller
2018-06-03 12:09:17 +02:00
parent f82f78b5b6
commit 5143f9577a
2 changed files with 11 additions and 6 deletions

View File

@ -237,9 +237,14 @@ TEST_CASE("Monadic operations", "[monadic]") {
REQUIRE(!o18r);
const tl::optional<int> o19 = tl::nullopt;
auto o19r =
std::move(o19).and_then([](int i) { return tl::make_optional(42); });
auto o19r = std::move(o19).and_then([](int i) { return tl::make_optional(42); });
REQUIRE(!o19r);
int i = 3;
tl::optional<int&> o20{i};
std::move(o20).and_then([](int& r){return tl::optional<int&>{++r};});
REQUIRE(o20);
REQUIRE(i == 4);
}
SECTION("constexpr and_then") {

View File

@ -1702,11 +1702,11 @@ public:
/// \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 &&>;
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))
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: result(nullopt);
}
@ -1725,11 +1725,11 @@ public:
/// \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 &&>;
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))
return has_value() ? detail::invoke(std::forward<F>(f), **this)
: result(nullopt);
}
#endif