Commit c5cff936 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

Avoid std::forward in folly/futures/

Summary: [Folly] Avoid `std::forward` in `folly/futures/` since function template instantiation is expensive at compile time and `std::forward` is, when used correctly, nothing more than library sugar for straightforward syntax.

Reviewed By: LeeHowes

Differential Revision: D22673234

fbshipit-source-id: f88bc8c8aa13797ae6eccf1a421a47ff135589e1
parent 28da027e
This diff is collapsed.
...@@ -222,8 +222,8 @@ auto makeExecutorLambda( ...@@ -222,8 +222,8 @@ auto makeExecutorLambda(
F&& func, F&& func,
typename std::enable_if<is_invocable_v<F>, int>::type = 0) { typename std::enable_if<is_invocable_v<F>, int>::type = 0) {
return return
[func = std::forward<F>(func)](Executor::KeepAlive<>&&, auto&&) mutable { [func = static_cast<F&&>(func)](Executor::KeepAlive<>&&, auto&&) mutable {
return std::forward<F>(func)(); return static_cast<F&&>(func)();
}; };
} }
...@@ -232,10 +232,10 @@ auto makeExecutorLambda( ...@@ -232,10 +232,10 @@ auto makeExecutorLambda(
F&& func, F&& func,
typename std::enable_if<!is_invocable_v<F>, int>::type = 0) { typename std::enable_if<!is_invocable_v<F>, int>::type = 0) {
using R = futures::detail::callableResult<T, F&&>; using R = futures::detail::callableResult<T, F&&>;
return [func = std::forward<F>(func)]( return [func = static_cast<F&&>(func)](
Executor::KeepAlive<>&&, Executor::KeepAlive<>&&,
typename R::Arg::ArgList::FirstArg&& param) mutable { typename R::Arg::ArgList::FirstArg&& param) mutable {
return std::forward<F>(func)(std::forward<decltype(param)>(param)); return static_cast<F&&>(func)(static_cast<decltype(param)>(param));
}; };
} }
......
...@@ -157,7 +157,7 @@ class FutureBase { ...@@ -157,7 +157,7 @@ class FutureBase {
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>:: typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type = 0> type = 0>
explicit FutureBase(in_place_t, Args&&... args) explicit FutureBase(in_place_t, Args&&... args)
: core_(Core::make(in_place, std::forward<Args>(args)...)) {} : core_(Core::make(in_place, static_cast<Args&&>(args)...)) {}
FutureBase(FutureBase<T> const&) = delete; FutureBase(FutureBase<T> const&) = delete;
FutureBase(SemiFuture<T>&&) noexcept; FutureBase(SemiFuture<T>&&) noexcept;
...@@ -344,7 +344,7 @@ class FutureBase { ...@@ -344,7 +344,7 @@ class FutureBase {
template <class E> template <class E>
void raise(E&& exception) { void raise(E&& exception) {
raise(make_exception_wrapper<typename std::remove_reference<E>::type>( raise(make_exception_wrapper<typename std::remove_reference<E>::type>(
std::forward<E>(exception))); static_cast<E&&>(exception)));
} }
/// Raises a FutureCancellation interrupt. /// Raises a FutureCancellation interrupt.
...@@ -530,7 +530,7 @@ class SemiFuture : private futures::detail::FutureBase<T> { ...@@ -530,7 +530,7 @@ class SemiFuture : private futures::detail::FutureBase<T> {
!isFuture<typename std::decay<T2>::type>::value && !isFuture<typename std::decay<T2>::type>::value &&
!isSemiFuture<typename std::decay<T2>::type>::value && !isSemiFuture<typename std::decay<T2>::type>::value &&
std::is_constructible<Try<T>, T2>::value>::type> std::is_constructible<Try<T>, T2>::value>::type>
/* implicit */ SemiFuture(T2&& val) : Base(std::forward<T2>(val)) {} /* implicit */ SemiFuture(T2&& val) : Base(static_cast<T2&&>(val)) {}
/// Construct a (logical) SemiFuture-of-void. /// Construct a (logical) SemiFuture-of-void.
/// ///
...@@ -558,7 +558,7 @@ class SemiFuture : private futures::detail::FutureBase<T> { ...@@ -558,7 +558,7 @@ class SemiFuture : private futures::detail::FutureBase<T> {
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>:: typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type = 0> type = 0>
explicit SemiFuture(in_place_t, Args&&... args) explicit SemiFuture(in_place_t, Args&&... args)
: Base(in_place, std::forward<Args>(args)...) {} : Base(in_place, static_cast<Args&&>(args)...) {}
SemiFuture(SemiFuture<T> const&) = delete; SemiFuture(SemiFuture<T> const&) = delete;
// movable // movable
...@@ -802,7 +802,7 @@ class SemiFuture : private futures::detail::FutureBase<T> { ...@@ -802,7 +802,7 @@ class SemiFuture : private futures::detail::FutureBase<T> {
template <class ExceptionType, class F> template <class ExceptionType, class F>
SemiFuture<T> deferError(F&& func) && { SemiFuture<T> deferError(F&& func) && {
return std::move(*this).deferError( return std::move(*this).deferError(
tag_t<ExceptionType>{}, std::forward<F>(func)); tag_t<ExceptionType>{}, static_cast<F&&>(func));
} }
/// Set an error continuation for this SemiFuture where the continuation can /// Set an error continuation for this SemiFuture where the continuation can
...@@ -1034,7 +1034,7 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1034,7 +1034,7 @@ class Future : private futures::detail::FutureBase<T> {
!isFuture<typename std::decay<T2>::type>::value && !isFuture<typename std::decay<T2>::type>::value &&
!isSemiFuture<typename std::decay<T2>::type>::value && !isSemiFuture<typename std::decay<T2>::type>::value &&
std::is_constructible<Try<T>, T2>::value>::type> std::is_constructible<Try<T>, T2>::value>::type>
/* implicit */ Future(T2&& val) : Base(std::forward<T2>(val)) {} /* implicit */ Future(T2&& val) : Base(static_cast<T2&&>(val)) {}
/// Construct a (logical) Future-of-void. /// Construct a (logical) Future-of-void.
/// ///
...@@ -1062,7 +1062,7 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1062,7 +1062,7 @@ class Future : private futures::detail::FutureBase<T> {
typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>:: typename std::enable_if<std::is_constructible<T, Args&&...>::value, int>::
type = 0> type = 0>
explicit Future(in_place_t, Args&&... args) explicit Future(in_place_t, Args&&... args)
: Base(in_place, std::forward<Args>(args)...) {} : Base(in_place, static_cast<Args&&>(args)...) {}
Future(Future<T> const&) = delete; Future(Future<T> const&) = delete;
// movable // movable
...@@ -1225,12 +1225,12 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1225,12 +1225,12 @@ class Future : private futures::detail::FutureBase<T> {
template <typename F> template <typename F>
Future<typename futures::detail::tryCallableResult<T, F>::value_type> then( Future<typename futures::detail::tryCallableResult<T, F>::value_type> then(
F&& func) && { F&& func) && {
return std::move(*this).thenTry(std::forward<F>(func)); return std::move(*this).thenTry(static_cast<F&&>(func));
} }
template <typename F> template <typename F>
Future<typename futures::detail::tryCallableResult<T, F>::value_type> Future<typename futures::detail::tryCallableResult<T, F>::value_type>
thenInline(F&& func) && { thenInline(F&& func) && {
return std::move(*this).thenTryInline(std::forward<F>(func)); return std::move(*this).thenTryInline(static_cast<F&&>(func));
} }
/// Variant where func is an member function /// Variant where func is an member function
...@@ -1435,7 +1435,7 @@ class Future : private futures::detail::FutureBase<T> { ...@@ -1435,7 +1435,7 @@ class Future : private futures::detail::FutureBase<T> {
template <class ExceptionType, class F> template <class ExceptionType, class F>
Future<T> thenError(F&& func) && { Future<T> thenError(F&& func) && {
return std::move(*this).thenError( return std::move(*this).thenError(
tag_t<ExceptionType>{}, std::forward<F>(func)); tag_t<ExceptionType>{}, static_cast<F&&>(func));
} }
/// Set an error continuation for this Future where the continuation can /// Set an error continuation for this Future where the continuation can
...@@ -2014,13 +2014,13 @@ std::pair<Promise<T>, Future<T>> makePromiseContract(Executor::KeepAlive<> e) { ...@@ -2014,13 +2014,13 @@ std::pair<Promise<T>, Future<T>> makePromiseContract(Executor::KeepAlive<> e) {
template <class F> template <class F>
auto makeAsyncTask(folly::Executor::KeepAlive<> ka, F&& func) { auto makeAsyncTask(folly::Executor::KeepAlive<> ka, F&& func) {
return [func = std::forward<F>(func), return [func = static_cast<F&&>(func),
ka = std::move(ka)](auto&& param) mutable { ka = std::move(ka)](auto&& param) mutable {
return via( return via(
ka, ka,
[func = std::move(func), [func = std::move(func),
param = std::forward<decltype(param)>(param)]() mutable { param = static_cast<decltype(param)>(param)]() mutable {
return std::forward<F>(func)(std::forward<decltype(param)>(param)); return static_cast<F&&>(func)(static_cast<decltype(param)&&>(param));
}); });
}; };
} }
...@@ -2115,26 +2115,26 @@ mapTry(Executor& exec, It first, It last, F func, int = 0); ...@@ -2115,26 +2115,26 @@ mapTry(Executor& exec, It first, It last, F func, int = 0);
template <class Collection, class F> template <class Collection, class F>
auto mapValue(Collection&& c, F&& func) auto mapValue(Collection&& c, F&& func)
-> decltype(mapValue(c.begin(), c.end(), func)) { -> decltype(mapValue(c.begin(), c.end(), func)) {
return mapValue(c.begin(), c.end(), std::forward<F>(func)); return mapValue(c.begin(), c.end(), static_cast<F&&>(func));
} }
template <class Collection, class F> template <class Collection, class F>
auto mapTry(Collection&& c, F&& func) auto mapTry(Collection&& c, F&& func)
-> decltype(mapTry(c.begin(), c.end(), func)) { -> decltype(mapTry(c.begin(), c.end(), func)) {
return mapTry(c.begin(), c.end(), std::forward<F>(func)); return mapTry(c.begin(), c.end(), static_cast<F&&>(func));
} }
// Sugar for the most common case // Sugar for the most common case
template <class Collection, class F> template <class Collection, class F>
auto mapValue(Executor& exec, Collection&& c, F&& func) auto mapValue(Executor& exec, Collection&& c, F&& func)
-> decltype(mapValue(exec, c.begin(), c.end(), func)) { -> decltype(mapValue(exec, c.begin(), c.end(), func)) {
return mapValue(exec, c.begin(), c.end(), std::forward<F>(func)); return mapValue(exec, c.begin(), c.end(), static_cast<F&&>(func));
} }
template <class Collection, class F> template <class Collection, class F>
auto mapTry(Executor& exec, Collection&& c, F&& func) auto mapTry(Executor& exec, Collection&& c, F&& func)
-> decltype(mapTry(exec, c.begin(), c.end(), func)) { -> decltype(mapTry(exec, c.begin(), c.end(), func)) {
return mapTry(exec, c.begin(), c.end(), std::forward<F>(func)); return mapTry(exec, c.begin(), c.end(), static_cast<F&&>(func));
} }
/// Carry out the computation contained in the given future if /// Carry out the computation contained in the given future if
...@@ -2544,10 +2544,10 @@ template <class Collection, class T, class F> ...@@ -2544,10 +2544,10 @@ template <class Collection, class T, class F>
auto reduce(Collection&& c, T&& initial, F&& func) -> decltype(folly::reduce( auto reduce(Collection&& c, T&& initial, F&& func) -> decltype(folly::reduce(
c.begin(), c.begin(),
c.end(), c.end(),
std::forward<T>(initial), static_cast<T&&>(initial),
std::forward<F>(func))) { static_cast<F&&>(func))) {
return folly::reduce( return folly::reduce(
c.begin(), c.end(), std::forward<T>(initial), std::forward<F>(func)); c.begin(), c.end(), static_cast<T&&>(initial), static_cast<F&&>(func));
} }
/** like reduce, but calls func on finished futures as they complete /** like reduce, but calls func on finished futures as they complete
...@@ -2562,10 +2562,10 @@ auto unorderedReduce(Collection&& c, T&& initial, F&& func) ...@@ -2562,10 +2562,10 @@ auto unorderedReduce(Collection&& c, T&& initial, F&& func)
-> decltype(folly::unorderedReduce( -> decltype(folly::unorderedReduce(
c.begin(), c.begin(),
c.end(), c.end(),
std::forward<T>(initial), static_cast<T&&>(initial),
std::forward<F>(func))) { static_cast<F&&>(func))) {
return folly::unorderedReduce( return folly::unorderedReduce(
c.begin(), c.end(), std::forward<T>(initial), std::forward<F>(func)); c.begin(), c.end(), static_cast<T&&>(initial), static_cast<F&&>(func));
} }
/// Carry out the computation contained in the given future if /// Carry out the computation contained in the given future if
......
...@@ -121,7 +121,7 @@ void Promise<T>::setException(exception_wrapper ew) { ...@@ -121,7 +121,7 @@ void Promise<T>::setException(exception_wrapper ew) {
template <class T> template <class T>
template <typename F> template <typename F>
void Promise<T>::setInterruptHandler(F&& fn) { void Promise<T>::setInterruptHandler(F&& fn) {
getCore().setInterruptHandler(std::forward<F>(fn)); getCore().setInterruptHandler(static_cast<F&&>(fn));
} }
template <class T> template <class T>
...@@ -141,14 +141,14 @@ template <class M> ...@@ -141,14 +141,14 @@ template <class M>
void Promise<T>::setValue(M&& v) { void Promise<T>::setValue(M&& v) {
static_assert(!std::is_same<T, void>::value, "Use setValue() instead"); static_assert(!std::is_same<T, void>::value, "Use setValue() instead");
setTry(Try<T>(std::forward<M>(v))); setTry(Try<T>(static_cast<M&&>(v)));
} }
template <class T> template <class T>
template <class F> template <class F>
void Promise<T>::setWith(F&& func) { void Promise<T>::setWith(F&& func) {
throwIfFulfilled(); throwIfFulfilled();
setTry(makeTryWith(std::forward<F>(func))); setTry(makeTryWith(static_cast<F&&>(func)));
} }
template <class T> template <class T>
......
...@@ -96,8 +96,8 @@ void retryingImpl(size_t k, Policy&& p, FF&& ff, Prom prom) { ...@@ -96,8 +96,8 @@ void retryingImpl(size_t k, Policy&& p, FF&& ff, Prom prom) {
auto f = makeFutureWith([&] { return ff(k++); }); auto f = makeFutureWith([&] { return ff(k++); });
std::move(f).thenTry([k, std::move(f).thenTry([k,
prom = std::move(prom), prom = std::move(prom),
pm = std::forward<Policy>(p), pm = static_cast<Policy&&>(p),
ffm = std::forward<FF>(ff)](Try<T>&& t) mutable { ffm = static_cast<FF&&>(ff)](Try<T>&& t) mutable {
if (t.hasValue()) { if (t.hasValue()) {
prom.setValue(std::move(t).value()); prom.setValue(std::move(t).value());
return; return;
...@@ -131,7 +131,7 @@ retrying(size_t k, Policy&& p, FF&& ff) { ...@@ -131,7 +131,7 @@ retrying(size_t k, Policy&& p, FF&& ff) {
auto prom = Promise<T>(); auto prom = Promise<T>();
auto f = prom.getFuture(); auto f = prom.getFuture();
retryingImpl( retryingImpl(
k, std::forward<Policy>(p), std::forward<FF>(ff), std::move(prom)); k, static_cast<Policy&&>(p), static_cast<FF&&>(ff), std::move(prom));
return f; return f;
} }
...@@ -143,13 +143,13 @@ typename std::enable_if< ...@@ -143,13 +143,13 @@ typename std::enable_if<
invoke_result_t<FF, size_t>>::Inner>>::type invoke_result_t<FF, size_t>>::Inner>>::type
retrying(size_t k, Policy&& p, FF&& ff) { retrying(size_t k, Policy&& p, FF&& ff) {
auto sf = folly::makeSemiFuture().deferExValue( auto sf = folly::makeSemiFuture().deferExValue(
[k, p = std::forward<Policy>(p), ff = std::forward<FF>(ff)]( [k, p = static_cast<Policy&&>(p), ff = static_cast<FF&&>(ff)](
Executor::KeepAlive<> ka, auto&&) mutable { Executor::KeepAlive<> ka, auto&&) mutable {
auto futureP = [p = std::forward<Policy>(p), ka]( auto futureP = [p = static_cast<Policy&&>(p), ka](
size_t kk, exception_wrapper e) { size_t kk, exception_wrapper e) {
return p(kk, std::move(e)).via(ka); return p(kk, std::move(e)).via(ka);
}; };
auto futureFF = [ff = std::forward<FF>(ff), ka = std::move(ka)]( auto futureFF = [ff = static_cast<FF&&>(ff), ka = std::move(ka)](
size_t v) { return ff(v).via(ka); }; size_t v) { return ff(v).via(ka); };
return retrying(k, std::move(futureP), std::move(futureFF)); return retrying(k, std::move(futureP), std::move(futureFF));
}); });
...@@ -159,15 +159,15 @@ retrying(size_t k, Policy&& p, FF&& ff) { ...@@ -159,15 +159,15 @@ retrying(size_t k, Policy&& p, FF&& ff) {
template <class Policy, class FF> template <class Policy, class FF>
invoke_result_t<FF, size_t> invoke_result_t<FF, size_t>
retrying(Policy&& p, FF&& ff, retrying_policy_raw_tag) { retrying(Policy&& p, FF&& ff, retrying_policy_raw_tag) {
auto q = [pm = std::forward<Policy>(p)](size_t k, exception_wrapper x) { auto q = [pm = static_cast<Policy&&>(p)](size_t k, exception_wrapper x) {
return makeFuture<bool>(pm(k, x)); return makeFuture<bool>(pm(k, x));
}; };
return retrying(0, std::move(q), std::forward<FF>(ff)); return retrying(0, std::move(q), static_cast<FF&&>(ff));
} }
template <class Policy, class FF> template <class Policy, class FF>
auto retrying(Policy&& p, FF&& ff, retrying_policy_fut_tag) { auto retrying(Policy&& p, FF&& ff, retrying_policy_fut_tag) {
return retrying(0, std::forward<Policy>(p), std::forward<FF>(ff)); return retrying(0, static_cast<Policy&&>(p), static_cast<FF&&>(ff));
} }
// jittered exponential backoff, clamped to [backoff_min, backoff_max] // jittered exponential backoff, clamped to [backoff_min, backoff_max]
...@@ -197,12 +197,12 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -197,12 +197,12 @@ retryingPolicyCappedJitteredExponentialBackoff(
double jitter_param, double jitter_param,
URNG&& rng, URNG&& rng,
Policy&& p) { Policy&& p) {
return [pm = std::forward<Policy>(p), return [pm = static_cast<Policy&&>(p),
max_tries, max_tries,
backoff_min, backoff_min,
backoff_max, backoff_max,
jitter_param, jitter_param,
rngp = std::forward<URNG>(rng)]( rngp = static_cast<URNG&&>(rng)](
size_t n, const exception_wrapper& ex) mutable { size_t n, const exception_wrapper& ex) mutable {
if (n == max_tries) { if (n == max_tries) {
return makeFuture(false); return makeFuture(false);
...@@ -231,7 +231,7 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -231,7 +231,7 @@ retryingPolicyCappedJitteredExponentialBackoff(
URNG&& rng, URNG&& rng,
Policy&& p, Policy&& p,
retrying_policy_raw_tag) { retrying_policy_raw_tag) {
auto q = [pm = std::forward<Policy>(p)]( auto q = [pm = static_cast<Policy&&>(p)](
size_t n, const exception_wrapper& e) { size_t n, const exception_wrapper& e) {
return makeFuture(pm(n, e)); return makeFuture(pm(n, e));
}; };
...@@ -240,7 +240,7 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -240,7 +240,7 @@ retryingPolicyCappedJitteredExponentialBackoff(
backoff_min, backoff_min,
backoff_max, backoff_max,
jitter_param, jitter_param,
std::forward<URNG>(rng), static_cast<URNG&&>(rng),
std::move(q)); std::move(q));
} }
...@@ -259,8 +259,8 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -259,8 +259,8 @@ retryingPolicyCappedJitteredExponentialBackoff(
backoff_min, backoff_min,
backoff_max, backoff_max,
jitter_param, jitter_param,
std::forward<URNG>(rng), static_cast<URNG&&>(rng),
std::forward<Policy>(p)); static_cast<Policy&&>(p));
} }
} // namespace detail } // namespace detail
...@@ -268,7 +268,8 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -268,7 +268,8 @@ retryingPolicyCappedJitteredExponentialBackoff(
template <class Policy, class FF> template <class Policy, class FF>
auto retrying(Policy&& p, FF&& ff) { auto retrying(Policy&& p, FF&& ff) {
using tag = typename detail::retrying_policy_traits<Policy>::tag; using tag = typename detail::retrying_policy_traits<Policy>::tag;
return detail::retrying(std::forward<Policy>(p), std::forward<FF>(ff), tag()); return detail::retrying(
static_cast<Policy&&>(p), static_cast<FF&&>(ff), tag());
} }
inline std::function<bool(size_t, const exception_wrapper&)> inline std::function<bool(size_t, const exception_wrapper&)>
...@@ -291,8 +292,8 @@ retryingPolicyCappedJitteredExponentialBackoff( ...@@ -291,8 +292,8 @@ retryingPolicyCappedJitteredExponentialBackoff(
backoff_min, backoff_min,
backoff_max, backoff_max,
jitter_param, jitter_param,
std::forward<URNG>(rng), static_cast<URNG&&>(rng),
std::forward<Policy>(p), static_cast<Policy&&>(p),
tag()); tag());
} }
......
...@@ -72,13 +72,13 @@ void SharedPromise<T>::setInterruptHandler( ...@@ -72,13 +72,13 @@ void SharedPromise<T>::setInterruptHandler(
template <class T> template <class T>
template <class M> template <class M>
void SharedPromise<T>::setValue(M&& v) { void SharedPromise<T>::setValue(M&& v) {
setTry(Try<T>(std::forward<M>(v))); setTry(Try<T>(static_cast<M&&>(v)));
} }
template <class T> template <class T>
template <class F> template <class F>
void SharedPromise<T>::setWith(F&& func) { void SharedPromise<T>::setWith(F&& func) {
setTry(makeTryWith(std::forward<F>(func))); setTry(makeTryWith(static_cast<F&&>(func)));
} }
template <class T> template <class T>
......
...@@ -445,7 +445,7 @@ class CoreBase { ...@@ -445,7 +445,7 @@ class CoreBase {
} else { } else {
auto oldInterruptHandler = interruptHandler_.exchange( auto oldInterruptHandler = interruptHandler_.exchange(
new InterruptHandlerImpl<typename std::decay<F>::type>( new InterruptHandlerImpl<typename std::decay<F>::type>(
std::forward<F>(fn)), static_cast<F&&>(fn)),
std::memory_order_relaxed); std::memory_order_relaxed);
if (oldInterruptHandler) { if (oldInterruptHandler) {
oldInterruptHandler->release(); oldInterruptHandler->release();
...@@ -530,7 +530,7 @@ class Core final : private ResultHolder<T>, public CoreBase { ...@@ -530,7 +530,7 @@ class Core final : private ResultHolder<T>, public CoreBase {
/// Result held will be the `T` constructed from forwarded `args` /// Result held will be the `T` constructed from forwarded `args`
template <typename... Args> template <typename... Args>
static Core<T>* make(in_place_t, Args&&... args) { static Core<T>* make(in_place_t, Args&&... args) {
return new Core<T>(in_place, std::forward<Args>(args)...); return new Core<T>(in_place, static_cast<Args&&>(args)...);
} }
/// Call only from consumer thread (since the consumer thread can modify the /// Call only from consumer thread (since the consumer thread can modify the
...@@ -582,7 +582,7 @@ class Core final : private ResultHolder<T>, public CoreBase { ...@@ -582,7 +582,7 @@ class Core final : private ResultHolder<T>, public CoreBase {
F&& func, F&& func,
std::shared_ptr<folly::RequestContext>&& context, std::shared_ptr<folly::RequestContext>&& context,
futures::detail::InlineContinuation allowInline) { futures::detail::InlineContinuation allowInline) {
Callback callback = [func = std::forward<F>(func)]( Callback callback = [func = static_cast<F&&>(func)](
CoreBase& coreBase, CoreBase& coreBase,
Executor::KeepAlive<>&& ka, Executor::KeepAlive<>&& ka,
exception_wrapper* ew) mutable { exception_wrapper* ew) mutable {
...@@ -645,7 +645,7 @@ class Core final : private ResultHolder<T>, public CoreBase { ...@@ -645,7 +645,7 @@ class Core final : private ResultHolder<T>, public CoreBase {
explicit Core(in_place_t, Args&&... args) noexcept( explicit Core(in_place_t, Args&&... args) noexcept(
std::is_nothrow_constructible<T, Args&&...>::value) std::is_nothrow_constructible<T, Args&&...>::value)
: CoreBase(State::OnlyResult, 1) { : CoreBase(State::OnlyResult, 1) {
new (&this->result_) Result(in_place, std::forward<Args>(args)...); new (&this->result_) Result(in_place, static_cast<Args&&>(args)...);
} }
~Core() override { ~Core() override {
......
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