#pragma once
-#include <folly/detail/TryDetail.h>
+#include <folly/Utility.h>
+
#include <stdexcept>
+#include <tuple>
namespace folly {
if (contains_ == Contains::VALUE) {
new (&value_)T(std::move(t.value_));
} else if (contains_ == Contains::EXCEPTION) {
- new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_));
+ new (&e_) exception_wrapper(std::move(t.e_));
}
}
new (&value_) T();
} else if (t.hasException()) {
contains_ = Contains::EXCEPTION;
- new (&e_) std::unique_ptr<exception_wrapper>(
- folly::make_unique<exception_wrapper>(t.exception()));
+ new (&e_) exception_wrapper(t.exception());
}
}
if (contains_ == Contains::VALUE) {
new (&value_)T(std::move(t.value_));
} else if (contains_ == Contains::EXCEPTION) {
- new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_));
+ new (&e_) exception_wrapper(std::move(t.e_));
}
return *this;
}
if (contains_ == Contains::VALUE) {
new (&value_)T(t.value_);
} else if (contains_ == Contains::EXCEPTION) {
- new (&e_)std::unique_ptr<exception_wrapper>();
- e_ = folly::make_unique<exception_wrapper>(*(t.e_));
+ new (&e_) exception_wrapper(t.e_);
}
}
if (contains_ == Contains::VALUE) {
new (&value_)T(t.value_);
} else if (contains_ == Contains::EXCEPTION) {
- new (&e_)std::unique_ptr<exception_wrapper>();
- e_ = folly::make_unique<exception_wrapper>(*(t.e_));
+ new (&e_) exception_wrapper(t.e_);
}
return *this;
}
if (LIKELY(contains_ == Contains::VALUE)) {
value_.~T();
} else if (UNLIKELY(contains_ == Contains::EXCEPTION)) {
- e_.~unique_ptr<exception_wrapper>();
+ e_.~exception_wrapper();
}
}
return value_;
}
+template <class T>
+const T&& Try<T>::value() const && {
+ throwIfFailed();
+ return std::move(value_);
+}
+
template <class T>
void Try<T>::throwIfFailed() const {
- if (contains_ != Contains::VALUE) {
- if (contains_ == Contains::EXCEPTION) {
- e_->throw_exception();
- } else {
- throw UsingUninitializedTry();
- }
+ switch (contains_) {
+ case Contains::VALUE:
+ return;
+ case Contains::EXCEPTION:
+ e_.throw_exception();
+ default:
+ try_detail::throwUsingUninitializedTry();
}
}
void Try<void>::throwIfFailed() const {
if (!hasValue_) {
- e_->throw_exception();
+ e_.throw_exception();
}
}
-template <typename T>
-inline T moveFromTry(Try<T>& t) {
- return std::move(t.value());
-}
-
-inline void moveFromTry(Try<void>& t) {
- return t.value();
-}
-
template <typename F>
typename std::enable_if<
!std::is_same<typename std::result_of<F()>::type, void>::value,
}
}
-template <typename... Ts>
-std::tuple<Ts...> unwrapTryTuple(std::tuple<folly::Try<Ts>...>&& ts) {
- return detail::TryTuple<Ts...>::unwrap(
- std::forward<std::tuple<folly::Try<Ts>...>>(ts));
+namespace try_detail {
+
+/**
+ * Trait that removes the layer of Try abstractions from the passed in type
+ */
+template <typename Type>
+struct RemoveTry;
+template <template <typename...> class TupleType, typename... Types>
+struct RemoveTry<TupleType<folly::Try<Types>...>> {
+ using type = TupleType<Types...>;
+};
+
+template <std::size_t... Indices, typename Tuple>
+auto unwrapTryTupleImpl(folly::index_sequence<Indices...>, Tuple&& instance) {
+ using std::get;
+ using ReturnType = typename RemoveTry<typename std::decay<Tuple>::type>::type;
+ return ReturnType{(get<Indices>(std::forward<Tuple>(instance)).value())...};
+}
+} // namespace try_detail
+
+template <typename Tuple>
+auto unwrapTryTuple(Tuple&& instance) {
+ using TupleDecayed = typename std::decay<Tuple>::type;
+ using Seq = folly::make_index_sequence<std::tuple_size<TupleDecayed>::value>;
+ return try_detail::unwrapTryTupleImpl(Seq{}, std::forward<Tuple>(instance));
}
-} // folly
+} // namespace folly