Commit e2fcfa38 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

No longer allow continuations taking non-const lvalue-ref

Summary: [Folly] No longer allow continuations taking non-const lvalue-ref, since that is not really necessary - callers can get all the same results using continuations taking non-const rvalue-ref instead.

Reviewed By: Orvid

Differential Revision: D8166011

fbshipit-source-id: 468d049c6034339f3caf1a82fbc8c755ec2f51e6
parent 51a23742
...@@ -981,7 +981,6 @@ template <class T> ...@@ -981,7 +981,6 @@ template <class T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!futures::detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::callableWith<F, exception_wrapper&>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { Future<T>::onError(F&& func) {
...@@ -1017,7 +1016,6 @@ template <class T> ...@@ -1017,7 +1016,6 @@ template <class T>
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!futures::detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::callableWith<F, exception_wrapper&>::value &&
futures::detail::Extract<F>::ReturnsFuture::value, futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
Future<T>::onError(F&& func) { Future<T>::onError(F&& func) {
......
...@@ -115,18 +115,12 @@ struct callableWith { ...@@ -115,18 +115,12 @@ struct callableWith {
template <typename T, typename F> template <typename T, typename F>
struct callableResult { struct callableResult {
typedef typename std::conditional< typedef typename std::conditional<
callableWith<F>::value, callableWith<F>::value,
detail::argResult<false, F>, detail::argResult<false, F>,
typename std::conditional<
callableWith<F, T&&>::value,
detail::argResult<false, F, T&&>,
typename std::conditional< typename std::conditional<
callableWith<F, T&>::value, callableWith<F, T&&>::value,
detail::argResult<false, F, T&>, detail::argResult<false, F, T&&>,
typename std::conditional< detail::argResult<true, F, Try<T>&&>>::type>::type Arg;
callableWith<F, Try<T>&&>::value,
detail::argResult<true, F, Try<T>&&>,
detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture; typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return; typedef Future<typename ReturnsFuture::Inner> Return;
}; };
...@@ -136,10 +130,7 @@ struct tryCallableResult { ...@@ -136,10 +130,7 @@ struct tryCallableResult {
typedef typename std::conditional< typedef typename std::conditional<
callableWith<F>::value, callableWith<F>::value,
detail::argResult<false, F>, detail::argResult<false, F>,
typename std::conditional< detail::argResult<true, F, Try<T>&&>>::type Arg;
callableWith<F, Try<T>&&>::value,
detail::argResult<true, F, Try<T>&&>,
detail::argResult<true, F, Try<T>&>>::type>::type Arg;
typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture; typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
typedef typename ReturnsFuture::Inner value_type; typedef typename ReturnsFuture::Inner value_type;
}; };
...@@ -149,10 +140,7 @@ struct valueCallableResult { ...@@ -149,10 +140,7 @@ struct valueCallableResult {
typedef typename std::conditional< typedef typename std::conditional<
callableWith<F>::value, callableWith<F>::value,
detail::argResult<false, F>, detail::argResult<false, F>,
typename std::conditional< detail::argResult<false, F, T&&>>::type Arg;
callableWith<F, T&&>::value,
detail::argResult<false, F, T&&>,
detail::argResult<false, F, T&>>::type>::type Arg;
typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture; typedef isFutureOrSemiFuture<typename Arg::Result> ReturnsFuture;
typedef typename ReturnsFuture::Inner value_type; typedef typename ReturnsFuture::Inner value_type;
typedef typename Arg::ArgList::FirstArg FirstArg; typedef typename Arg::ArgList::FirstArg FirstArg;
......
...@@ -872,7 +872,6 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -872,7 +872,6 @@ class Future : private futures::detail::FutureBase<T> {
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!futures::detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::callableWith<F, exception_wrapper&>::value &&
!futures::detail::Extract<F>::ReturnsFuture::value, !futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
...@@ -881,7 +880,6 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -881,7 +880,6 @@ class Future : private futures::detail::FutureBase<T> {
template <class F> template <class F>
typename std::enable_if< typename std::enable_if<
!futures::detail::callableWith<F, exception_wrapper>::value && !futures::detail::callableWith<F, exception_wrapper>::value &&
!futures::detail::callableWith<F, exception_wrapper&>::value &&
futures::detail::Extract<F>::ReturnsFuture::value, futures::detail::Extract<F>::ReturnsFuture::value,
Future<T>>::type Future<T>>::type
onError(F&& func); onError(F&& func);
......
...@@ -879,39 +879,31 @@ TEST(Future, special) { ...@@ -879,39 +879,31 @@ TEST(Future, special) {
} }
TEST(Future, then) { TEST(Future, then) {
auto f = makeFuture<std::string>("0") auto f =
.then([](){ makeFuture<std::string>("0")
return makeFuture<std::string>("1"); }) .then([]() { return makeFuture<std::string>("1"); })
.then([](Try<std::string>&& t) { .then(
return makeFuture(t.value() + ";2"); }) [](Try<std::string>&& t) { return makeFuture(t.value() + ";2"); })
.then([](const Try<std::string>&& t) { .then([](const Try<std::string>&& t) {
return makeFuture(t.value() + ";3"); }) return makeFuture(t.value() + ";3");
.then([](Try<std::string>& t) { })
return makeFuture(t.value() + ";4"); }) .then([](const Try<std::string>& t) {
.then([](const Try<std::string>& t) { return makeFuture(t.value() + ";4");
return makeFuture(t.value() + ";5"); }) })
.then([](Try<std::string> t) { .then([](Try<std::string> t) { return makeFuture(t.value() + ";5"); })
return makeFuture(t.value() + ";6"); }) .then([](const Try<std::string> t) {
.then([](const Try<std::string> t) { return makeFuture(t.value() + ";6");
return makeFuture(t.value() + ";7"); }) })
.then([](std::string&& s) { .then([](std::string&& s) { return makeFuture(s + ";7"); })
return makeFuture(s + ";8"); }) .then([](const std::string&& s) { return makeFuture(s + ";8"); })
.then([](const std::string&& s) { .then([](const std::string& s) { return makeFuture(s + ";9"); })
return makeFuture(s + ";9"); }) .then([](std::string s) { return makeFuture(s + ";10"); })
.then([](std::string& s) { .then([](const std::string s) { return makeFuture(s + ";11"); });
return makeFuture(s + ";10"); }) EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11");
.then([](const std::string& s) {
return makeFuture(s + ";11"); })
.then([](std::string s) {
return makeFuture(s + ";12"); })
.then([](const std::string s) {
return makeFuture(s + ";13"); })
;
EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11;12;13");
} }
static folly::Future<std::string> doWorkStaticTry(Try<std::string>&& t) { static folly::Future<std::string> doWorkStaticTry(Try<std::string>&& t) {
return makeFuture(t.value() + ";8"); return makeFuture(t.value() + ";7");
} }
TEST(Future, thenTrythenValue) { TEST(Future, thenTrythenValue) {
...@@ -923,25 +915,21 @@ TEST(Future, thenTrythenValue) { ...@@ -923,25 +915,21 @@ TEST(Future, thenTrythenValue) {
.thenTry([](const Try<std::string>&& t) { .thenTry([](const Try<std::string>&& t) {
return makeFuture(t.value() + ";3"); return makeFuture(t.value() + ";3");
}) })
.thenTry(
[](Try<std::string>& t) { return makeFuture(t.value() + ";4"); })
.thenTry([](const Try<std::string>& t) { .thenTry([](const Try<std::string>& t) {
return makeFuture(t.value() + ";5"); return makeFuture(t.value() + ";4");
}) })
.thenTry( .thenTry(
[](Try<std::string> t) { return makeFuture(t.value() + ";6"); }) [](Try<std::string> t) { return makeFuture(t.value() + ";5"); })
.thenTry([](const Try<std::string> t) { .thenTry([](const Try<std::string> t) {
return makeFuture(t.value() + ";7"); return makeFuture(t.value() + ";6");
}) })
.thenTry(doWorkStaticTry) .thenTry(doWorkStaticTry)
.thenValue([](std::string&& s) { return makeFuture(s + ";9"); }) .thenValue([](std::string&& s) { return makeFuture(s + ";8"); })
.thenValue( .thenValue([](const std::string&& s) { return makeFuture(s + ";9"); })
[](const std::string&& s) { return makeFuture(s + ";10"); }) .thenValue([](const std::string& s) { return makeFuture(s + ";10"); })
.thenValue([](std::string& s) { return makeFuture(s + ";11"); }) .thenValue([](std::string s) { return makeFuture(s + ";11"); })
.thenValue([](const std::string& s) { return makeFuture(s + ";12"); }) .thenValue([](const std::string s) { return makeFuture(s + ";12"); });
.thenValue([](std::string s) { return makeFuture(s + ";13"); }) EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11;12");
.thenValue([](const std::string s) { return makeFuture(s + ";14"); });
EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11;12;13;14");
} }
TEST(Future, thenTry) { TEST(Future, thenTry) {
...@@ -1075,7 +1063,7 @@ TEST(Future, thenStdFunction) { ...@@ -1075,7 +1063,7 @@ TEST(Future, thenStdFunction) {
EXPECT_EQ(f.value(), 42); EXPECT_EQ(f.value(), 42);
} }
{ {
std::function<int(Try<int>&)> fn = [](Try<int>& t){ return t.value() + 2; }; std::function<int(Try<int>)> fn = [](Try<int> t) { return t.value() + 2; };
auto f = makeFuture(1).then(std::move(fn)); auto f = makeFuture(1).then(std::move(fn));
EXPECT_EQ(f.value(), 3); EXPECT_EQ(f.value(), 3);
} }
......
...@@ -22,11 +22,7 @@ TEST(Basic, thenVariants) { ...@@ -22,11 +22,7 @@ TEST(Basic, thenVariants) {
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>>());}
{Future<B> f = someFuture<A>().then([&](Try<A>){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](Try<A>){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&&>, &anObject);}
...@@ -42,11 +38,7 @@ TEST(Basic, thenVariants) { ...@@ -42,11 +38,7 @@ TEST(Basic, thenVariants) {
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A>());}
{Future<B> f = someFuture<A>().then([&](A){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](A){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A&>());}
{Future<B> f = someFuture<A>().then([&](A&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then([&](){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&&>);}
...@@ -63,11 +55,7 @@ TEST(Basic, thenVariants) { ...@@ -63,11 +55,7 @@ TEST(Basic, thenVariants) {
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>>());}
{Future<B> f = someFuture<A>().then([&](Try<A>){return B();});} {Future<B> f = someFuture<A>().then([&](Try<A>){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A&&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&&>, &anObject);}
...@@ -83,10 +71,6 @@ TEST(Basic, thenVariants) { ...@@ -83,10 +71,6 @@ TEST(Basic, thenVariants) {
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, A>());}
{Future<B> f = someFuture<A>().then([&](A){return B();});} {Future<B> f = someFuture<A>().then([&](A){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&>, &anObject);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A&>());}
{Future<B> f = someFuture<A>().then([&](A&){return B();});}
{Future<B> f = someFuture<A>().then([&](){return B();});} {Future<B> f = someFuture<A>().then([&](){return B();});}
} }
...@@ -106,16 +106,6 @@ TEST(Then, tryRValueReference) { ...@@ -106,16 +106,6 @@ TEST(Then, tryRValueReference) {
EXPECT_EQ(future.value(), 23); EXPECT_EQ(future.value(), 23);
} }
TEST(Then, tryLValueReference) {
auto future = makeFuture<Widget>(23).then(
[](Try<Widget>& t) {
EXPECT_EQ(t.value().copied_, 0);
EXPECT_EQ(t.value().moved_, 2);
return t.value().v_;
});
EXPECT_EQ(future.value(), 23);
}
TEST(Then, tryConstLValueReference) { TEST(Then, tryConstLValueReference) {
auto future = makeFuture<Widget>(23).then( auto future = makeFuture<Widget>(23).then(
[](const Try<Widget>& t) { [](const Try<Widget>& t) {
...@@ -166,16 +156,6 @@ TEST(Then, rValueReference) { ...@@ -166,16 +156,6 @@ TEST(Then, rValueReference) {
EXPECT_EQ(future.value(), 23); EXPECT_EQ(future.value(), 23);
} }
TEST(Then, lValueReference) {
auto future = makeFuture<Widget>(23).then(
[](Widget& w) {
EXPECT_EQ(w.copied_, 0);
EXPECT_EQ(w.moved_, 2);
return w.v_;
});
EXPECT_EQ(future.value(), 23);
}
TEST(Then, constLValueReference) { TEST(Then, constLValueReference) {
auto future = makeFuture<Widget>(23).then( auto future = makeFuture<Widget>(23).then(
[](const Widget& w) { [](const Widget& w) {
......
...@@ -332,7 +332,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -332,7 +332,7 @@ TEST(Wait, WaitPlusThen) {
EXPECT_EQ(f.value(), 42); EXPECT_EQ(f.value(), 42);
f.wait(); f.wait();
auto continuation = 0; auto continuation = 0;
EXPECT_NO_THROW(f.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
} }
...@@ -352,7 +352,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -352,7 +352,7 @@ TEST(Wait, WaitPlusThen) {
EXPECT_FALSE(f.isReady()); // deterministically passes in practice EXPECT_FALSE(f.isReady()); // deterministically passes in practice
f.wait(); f.wait();
EXPECT_THROW(f.then([](auto&) {}), std::logic_error); EXPECT_THROW(f.then([](auto&&) {}), std::logic_error);
t.join(); t.join();
} }
...@@ -366,7 +366,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -366,7 +366,7 @@ TEST(Wait, WaitPlusThen) {
EXPECT_EQ(f.value(), 42); EXPECT_EQ(f.value(), 42);
f.wait(std::chrono::seconds(10)); f.wait(std::chrono::seconds(10));
auto continuation = 0; auto continuation = 0;
EXPECT_NO_THROW(f.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
} }
...@@ -388,7 +388,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -388,7 +388,7 @@ TEST(Wait, WaitPlusThen) {
f.wait(std::chrono::seconds(10)); f.wait(std::chrono::seconds(10));
EXPECT_TRUE(f.isReady()); // deterministically passes in practice EXPECT_TRUE(f.isReady()); // deterministically passes in practice
auto continuation = 0; auto continuation = 0;
EXPECT_NO_THROW(f.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
t.join(); t.join();
} }
...@@ -400,7 +400,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -400,7 +400,7 @@ TEST(Wait, WaitPlusThen) {
auto f = p.getFuture(); auto f = p.getFuture();
f.wait(milliseconds(1)); f.wait(milliseconds(1));
auto continuation = 0; auto continuation = 0;
EXPECT_NO_THROW(f.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 0); EXPECT_EQ(continuation, 0);
} }
...@@ -416,7 +416,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -416,7 +416,7 @@ TEST(Wait, WaitPlusThen) {
auto continuation = 0; auto continuation = 0;
InlineExecutor e; InlineExecutor e;
auto f2 = std::move(f).via(&e); auto f2 = std::move(f).via(&e);
EXPECT_NO_THROW(f2.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f2.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
} }
...@@ -438,7 +438,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -438,7 +438,7 @@ TEST(Wait, WaitPlusThen) {
f.wait(); f.wait();
InlineExecutor e; InlineExecutor e;
auto f2 = std::move(f).via(&e); auto f2 = std::move(f).via(&e);
EXPECT_THROW(f2.then([](auto&) {}), std::logic_error); EXPECT_THROW(f2.then([](auto&&) {}), std::logic_error);
t.join(); t.join();
} }
...@@ -454,7 +454,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -454,7 +454,7 @@ TEST(Wait, WaitPlusThen) {
auto continuation = 0; auto continuation = 0;
InlineExecutor e; InlineExecutor e;
auto f2 = std::move(f).via(&e); auto f2 = std::move(f).via(&e);
EXPECT_NO_THROW(f2.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f2.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
} }
...@@ -478,7 +478,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -478,7 +478,7 @@ TEST(Wait, WaitPlusThen) {
auto continuation = 0; auto continuation = 0;
InlineExecutor e; InlineExecutor e;
auto f2 = std::move(f).via(&e); auto f2 = std::move(f).via(&e);
EXPECT_NO_THROW(f2.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f2.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
t.join(); t.join();
} }
...@@ -492,7 +492,7 @@ TEST(Wait, WaitPlusThen) { ...@@ -492,7 +492,7 @@ TEST(Wait, WaitPlusThen) {
auto continuation = 0; auto continuation = 0;
InlineExecutor e; InlineExecutor e;
auto f2 = std::move(f).via(&e); auto f2 = std::move(f).via(&e);
EXPECT_NO_THROW(f2.then([&](auto& v) { continuation = v; })); EXPECT_NO_THROW(f2.then([&](auto&& v) { continuation = v; }));
EXPECT_EQ(continuation, 0); EXPECT_EQ(continuation, 0);
p.setValue(42); p.setValue(42);
EXPECT_EQ(continuation, 42); EXPECT_EQ(continuation, 42);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment