From 5bad4e9ff7c7bdca58b3e0c312b7f4f54dcea936 Mon Sep 17 00:00:00 2001 From: Andrii Grynenko Date: Fri, 13 Nov 2015 13:47:27 -0800 Subject: [PATCH] Make collect work for types with no default constructors Summary: This doesn't make the code less efficient, because RVO can't be used for CollectVariadicContext. Thus moving existing tuple vs constructing new tuple by moving all values from other tuple (where each value is wrapped in folly::Optional) should be pretty much the same. Reviewed By: hannesr Differential Revision: D2650293 fb-gh-sync-id: 648a358bf093a0bb9d058a997af9bf59014ad77c --- folly/futures/detail/Core.h | 25 ++++++++++++++++++++++--- folly/futures/test/CollectTest.cpp | 11 +++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/folly/futures/detail/Core.h b/folly/futures/detail/Core.h index bca540de..b0bb2ff7 100644 --- a/folly/futures/detail/Core.h +++ b/folly/futures/detail/Core.h @@ -410,18 +410,37 @@ struct CollectVariadicContext { p.setException(std::move(t.exception())); } } else if (!threw) { - std::get(results) = std::move(t.value()); + std::get(results) = std::move(t); } } ~CollectVariadicContext() { if (!threw.exchange(true)) { - p.setValue(std::move(results)); + p.setValue(unwrap(std::move(results))); } } Promise> p; - std::tuple results; + std::tuple...> results; std::atomic threw {false}; typedef Future> type; + + private: + template + static std::tuple unwrap(std::tuple...>&& o, + Ts2&&... ts2) { + static_assert(sizeof...(ts2) < + std::tuple_size...>>::value, + "Non-templated unwrap should be used instead"); + assert(std::get(o).hasValue()); + + return unwrap(std::move(o), + std::forward(ts2)..., + std::move(*std::get(o))); + } + + static std::tuple unwrap(std::tuple...>&& o, + Ts&&... ts) { + return std::tuple(std::forward(ts)...); + } }; template