Commit 97705d14 authored by Orvid King's avatar Orvid King Committed by Facebook Github Bot

Fix the final issue on MSVC 2017 Update 7

Summary: MSVC 2017 Update 7 has issues with expanding empty parameter packs in certain situations.

Reviewed By: yfeldblum

Differential Revision: D7983735

fbshipit-source-id: d90c01a36885b94269b3dbc260142abd6556102d
parent 8521e599
...@@ -261,6 +261,29 @@ template <class T> ...@@ -261,6 +261,29 @@ template <class T>
FutureBase<T>::FutureBase(futures::detail::EmptyConstruct) noexcept FutureBase<T>::FutureBase(futures::detail::EmptyConstruct) noexcept
: core_(nullptr) {} : core_(nullptr) {}
// MSVC 2017 Update 7 released with a bug that causes issues expanding to an
// empty parameter pack when invoking a templated member function. It should
// be fixed for MSVC 2017 Update 8.
// TODO: Remove.
namespace detail_msvc_15_7_workaround {
template <bool isTry, typename State, typename T>
decltype(auto) invoke(State& state, Try<T>& /* t */) {
return state.invoke();
}
template <bool isTry, typename State, typename T, typename Arg>
decltype(auto) invoke(State& state, Try<T>& t) {
return state.invoke(t.template get<isTry, Arg>());
}
template <bool isTry, typename State, typename T>
decltype(auto) tryInvoke(State& state, Try<T>& /* t */) {
return state.tryInvoke();
}
template <bool isTry, typename State, typename T, typename Arg>
decltype(auto) tryInvoke(State& state, Try<T>& t) {
return state.tryInvoke(t.template get<isTry, Arg>());
}
} // namespace detail_msvc_15_7_workaround
// then // then
// Variant: returns a value // Variant: returns a value
...@@ -318,8 +341,10 @@ FutureBase<T>::thenImplementation( ...@@ -318,8 +341,10 @@ FutureBase<T>::thenImplementation(
if (!isTry && t.hasException()) { if (!isTry && t.hasException()) {
state.setException(std::move(t.exception())); state.setException(std::move(t.exception()));
} else { } else {
state.setTry(makeTryWith( state.setTry(makeTryWith([&] {
[&] { return state.invoke(t.template get<isTry, Args>()...); })); return detail_msvc_15_7_workaround::
invoke<isTry, decltype(state), T, Args...>(state, t);
}));
} }
}); });
return f; return f;
...@@ -369,7 +394,8 @@ FutureBase<T>::thenImplementation( ...@@ -369,7 +394,8 @@ FutureBase<T>::thenImplementation(
} else { } else {
// Ensure that if function returned a SemiFuture we correctly chain // Ensure that if function returned a SemiFuture we correctly chain
// potential deferral. // potential deferral.
auto tf2 = state.tryInvoke(t.template get<isTry, Args>()...); auto tf2 = detail_msvc_15_7_workaround::
tryInvoke<isTry, decltype(state), T, Args...>(state, t);
if (tf2.hasException()) { if (tf2.hasException()) {
state.setException(std::move(tf2.exception())); state.setException(std::move(tf2.exception()));
} else { } else {
......
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