in some circumstances, but I think it should be explicit not implicit
in the destruction of the Future used to create it.
*/
- setCallback_([ funcm = std::forward<F>(func), pm = std::move(p) ](
- Try<T> && t) mutable {
- if (!isTry && t.hasException()) {
- pm.setException(std::move(t.exception()));
- } else {
- pm.setWith([&]() { return funcm(t.template get<isTry, Args>()...); });
- }
- });
+ setCallback_(
+ [ func = std::forward<F>(func), pm = std::move(p) ](Try<T> && t) mutable {
+ if (!isTry && t.hasException()) {
+ pm.setException(std::move(t.exception()));
+ } else {
+ pm.setWith([&]() {
+ return std::move(func)(t.template get<isTry, Args>()...);
+ });
+ }
+ });
return f;
}
auto f = p.getFuture();
f.core_->setExecutorNoLock(getExecutor());
- setCallback_([ funcm = std::forward<F>(func), pm = std::move(p) ](
+ setCallback_([ func = std::forward<F>(func), pm = std::move(p) ](
Try<T> && t) mutable {
auto ew = [&] {
if (!isTry && t.hasException()) {
return std::move(t.exception());
} else {
try {
- auto f2 = funcm(t.template get<isTry, Args>()...);
+ auto f2 = std::move(func)(t.template get<isTry, Args>()...);
// that didn't throw, now we can steal p
f2.setCallback_([p = std::move(pm)](Try<B> && b) mutable {
p.setTry(std::move(b));
p.core_->setInterruptHandlerNoLock(core_->getInterruptHandler());
auto f = p.getFuture();
- setCallback_([ funcm = std::forward<F>(func), pm = std::move(p) ](
- Try<T> && t) mutable {
- if (!t.template withException<Exn>(
- [&](Exn& e) { pm.setWith([&] { return funcm(e); }); })) {
- pm.setTry(std::move(t));
- }
- });
+ setCallback_(
+ [ func = std::forward<F>(func), pm = std::move(p) ](Try<T> && t) mutable {
+ if (!t.template withException<Exn>([&](Exn& e) {
+ pm.setWith([&] { return std::move(func)(e); });
+ })) {
+ pm.setTry(std::move(t));
+ }
+ });
return f;
}
Promise<T> p;
auto f = p.getFuture();
- setCallback_([ pm = std::move(p), funcm = std::forward<F>(func) ](
+ setCallback_([ pm = std::move(p), func = std::forward<F>(func) ](
Try<T> && t) mutable {
if (!t.template withException<Exn>([&](Exn& e) {
auto ew = [&] {
try {
- auto f2 = funcm(e);
+ auto f2 = std::move(func)(e);
f2.setCallback_([pm = std::move(pm)](Try<T> && t2) mutable {
pm.setTry(std::move(t2));
});
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [ pm = std::move(p), funcm = std::forward<F>(func) ](Try<T> t) mutable {
+ [ pm = std::move(p), func = std::forward<F>(func) ](Try<T> t) mutable {
if (t.hasException()) {
auto ew = [&] {
try {
- auto f2 = funcm(std::move(t.exception()));
+ auto f2 = std::move(func)(std::move(t.exception()));
f2.setCallback_([pm = std::move(pm)](Try<T> t2) mutable {
pm.setTry(std::move(t2));
});
Promise<T> p;
auto f = p.getFuture();
setCallback_(
- [ pm = std::move(p), funcm = std::forward<F>(func) ](Try<T> t) mutable {
+ [ pm = std::move(p), func = std::forward<F>(func) ](Try<T> t) mutable {
if (t.hasException()) {
- pm.setWith([&] { return funcm(std::move(t.exception())); });
+ pm.setWith([&] { return std::move(func)(std::move(t.exception())); });
} else {
pm.setTry(std::move(t));
}
TEST(Future, makeFutureNoThrow) {
makeFuture().value();
}
+
+TEST(Future, invokeCallbackReturningValueAsRvalue) {
+ struct Foo {
+ int operator()(int x) & {
+ return x + 1;
+ }
+ int operator()(int x) const& {
+ return x + 2;
+ }
+ int operator()(int x) && {
+ return x + 3;
+ }
+ };
+
+ Foo foo;
+ Foo const cfoo;
+
+ // The callback will be copied when given as lvalue or const ref, and moved
+ // if provided as rvalue. Either way, it should be executed as rvalue.
+ EXPECT_EQ(103, makeFuture<int>(100).then(foo).value());
+ EXPECT_EQ(203, makeFuture<int>(200).then(cfoo).value());
+ EXPECT_EQ(303, makeFuture<int>(300).then(Foo()).value());
+}
+
+TEST(Future, invokeCallbackReturningFutureAsRvalue) {
+ struct Foo {
+ Future<int> operator()(int x) & {
+ return x + 1;
+ }
+ Future<int> operator()(int x) const& {
+ return x + 2;
+ }
+ Future<int> operator()(int x) && {
+ return x + 3;
+ }
+ };
+
+ Foo foo;
+ Foo const cfoo;
+
+ // The callback will be copied when given as lvalue or const ref, and moved
+ // if provided as rvalue. Either way, it should be executed as rvalue.
+ EXPECT_EQ(103, makeFuture<int>(100).then(foo).value());
+ EXPECT_EQ(203, makeFuture<int>(200).then(cfoo).value());
+ EXPECT_EQ(303, makeFuture<int>(300).then(Foo()).value());
+}