-template <typename... Ts, typename THead, typename... Fs>
-typename std::enable_if<sizeof...(Fs) == 0, void>::type
-collectAllVariadicHelper(std::shared_ptr<VariadicContext<Ts...>> ctx,
- THead&& head, Fs&&... tail) {
- head.setCallback_([ctx](Try<typename THead::value_type>&& t) {
- std::get<sizeof...(Ts) - sizeof...(Fs) - 1>(ctx->results) = std::move(t);
- });
+template <typename... Ts>
+struct CollectVariadicContext {
+ CollectVariadicContext() {}
+ template <typename T, size_t I>
+ inline void setPartialResult(Try<T>& t) {
+ if (t.hasException()) {
+ if (!threw.exchange(true)) {
+ p.setException(std::move(t.exception()));
+ }
+ } else if (!threw) {
+ std::get<I>(results) = std::move(t);
+ }
+ }
+ ~CollectVariadicContext() {
+ if (!threw.exchange(true)) {
+ p.setValue(unwrap(std::move(results)));
+ }
+ }
+ Promise<std::tuple<Ts...>> p;
+ std::tuple<folly::Try<Ts>...> results;
+ std::atomic<bool> threw {false};
+ typedef Future<std::tuple<Ts...>> type;
+
+ private:
+ template <typename... Ts2>
+ static std::tuple<Ts...> unwrap(std::tuple<folly::Try<Ts>...>&& o,
+ Ts2&&... ts2) {
+ static_assert(sizeof...(ts2) <
+ std::tuple_size<std::tuple<folly::Try<Ts>...>>::value,
+ "Non-templated unwrap should be used instead");
+ assert(std::get<sizeof...(ts2)>(o).hasValue());
+
+ return unwrap(std::move(o),
+ std::forward<Ts2>(ts2)...,
+ std::move(*std::get<sizeof...(ts2)>(o)));
+ }
+
+ static std::tuple<Ts...> unwrap(std::tuple<folly::Try<Ts>...>&& /* o */,
+ Ts&&... ts) {
+ return std::tuple<Ts...>(std::forward<Ts>(ts)...);
+ }
+};
+
+template <template <typename...> class T, typename... Ts>
+void collectVariadicHelper(const std::shared_ptr<T<Ts...>>& /* ctx */) {
+ // base case