From: Yedidya Feldblum Date: Thu, 19 May 2016 09:20:24 +0000 (-0700) Subject: Extract Try to top-level X-Git-Tag: 2016.07.26~215 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=a56a988a8cd07c7e3250f27594b8f92c9274b30d Extract Try to top-level Summary: [Folly] Extract `Try` to top-level. It was in `folly/futures/`, but this diff moves it to `folly/`. It is needed for futures, but it is are more general than futures and can be used separately. Use `folly/Try.h` instead of `folly/futures/Try.h`. Also fixes up all `#include` sites: hg grep -lw folly/futures/Try | xargs perl -pi -e 's,\bfolly/futures/Try\b,folly/Try,g' Reviewed By: markisaa Differential Revision: D3309908 fbshipit-source-id: cdf13f0ac0b0e36aa07e0f1d04870d06500c5874 --- diff --git a/folly/Makefile.am b/folly/Makefile.am index 1cc7a2ee..1b28ff7f 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -173,8 +173,6 @@ nobase_follyinclude_HEADERS = \ futures/SharedPromise-inl.h \ futures/ThreadWheelTimekeeper.h \ futures/Timekeeper.h \ - futures/Try-inl.h \ - futures/Try.h \ futures/detail/Core.h \ futures/detail/FSM.h \ futures/detail/Types.h \ @@ -345,6 +343,8 @@ nobase_follyinclude_HEADERS = \ ThreadName.h \ TimeoutQueue.h \ Traits.h \ + Try-inl.h \ + Try.h \ Unicode.h \ Function.h \ Unit.h \ diff --git a/folly/Try-inl.h b/folly/Try-inl.h new file mode 100644 index 00000000..ba988e3d --- /dev/null +++ b/folly/Try-inl.h @@ -0,0 +1,176 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace folly { + +template +Try::Try(Try&& t) noexcept : contains_(t.contains_) { + if (contains_ == Contains::VALUE) { + new (&value_)T(std::move(t.value_)); + } else if (contains_ == Contains::EXCEPTION) { + new (&e_)std::unique_ptr(std::move(t.e_)); + } +} + +template +template +Try::Try(typename std::enable_if::value, + Try const&>::type t) + : contains_(Contains::NOTHING) { + if (t.hasValue()) { + contains_ = Contains::VALUE; + new (&value_) T(); + } else if (t.hasException()) { + contains_ = Contains::EXCEPTION; + new (&e_) std::unique_ptr( + folly::make_unique(t.exception())); + } +} + +template +Try& Try::operator=(Try&& t) noexcept { + if (this == &t) { + return *this; + } + + this->~Try(); + contains_ = t.contains_; + if (contains_ == Contains::VALUE) { + new (&value_)T(std::move(t.value_)); + } else if (contains_ == Contains::EXCEPTION) { + new (&e_)std::unique_ptr(std::move(t.e_)); + } + return *this; +} + +template +Try::Try(const Try& t) { + static_assert( + std::is_copy_constructible::value, + "T must be copyable for Try to be copyable"); + contains_ = t.contains_; + if (contains_ == Contains::VALUE) { + new (&value_)T(t.value_); + } else if (contains_ == Contains::EXCEPTION) { + new (&e_)std::unique_ptr(); + e_ = folly::make_unique(*(t.e_)); + } +} + +template +Try& Try::operator=(const Try& t) { + static_assert( + std::is_copy_constructible::value, + "T must be copyable for Try to be copyable"); + this->~Try(); + contains_ = t.contains_; + if (contains_ == Contains::VALUE) { + new (&value_)T(t.value_); + } else if (contains_ == Contains::EXCEPTION) { + new (&e_)std::unique_ptr(); + e_ = folly::make_unique(*(t.e_)); + } + return *this; +} + +template +Try::~Try() { + if (LIKELY(contains_ == Contains::VALUE)) { + value_.~T(); + } else if (UNLIKELY(contains_ == Contains::EXCEPTION)) { + e_.~unique_ptr(); + } +} + +template +T& Try::value() & { + throwIfFailed(); + return value_; +} + +template +T&& Try::value() && { + throwIfFailed(); + return std::move(value_); +} + +template +const T& Try::value() const & { + throwIfFailed(); + return value_; +} + +template +void Try::throwIfFailed() const { + if (contains_ != Contains::VALUE) { + if (contains_ == Contains::EXCEPTION) { + e_->throwException(); + } else { + throw UsingUninitializedTry(); + } + } +} + +void Try::throwIfFailed() const { + if (!hasValue_) { + e_->throwException(); + } +} + +template +inline T moveFromTry(Try& t) { + return std::move(t.value()); +} + +inline void moveFromTry(Try& t) { + return t.value(); +} + +template +typename std::enable_if< + !std::is_same::type, void>::value, + Try::type>>::type +makeTryWith(F&& f) { + typedef typename std::result_of::type ResultType; + try { + return Try(f()); + } catch (std::exception& e) { + return Try(exception_wrapper(std::current_exception(), e)); + } catch (...) { + return Try(exception_wrapper(std::current_exception())); + } +} + +template +typename std::enable_if< + std::is_same::type, void>::value, + Try>::type +makeTryWith(F&& f) { + try { + f(); + return Try(); + } catch (std::exception& e) { + return Try(exception_wrapper(std::current_exception(), e)); + } catch (...) { + return Try(exception_wrapper(std::current_exception())); + } +} + +} // folly diff --git a/folly/Try.h b/folly/Try.h new file mode 100644 index 00000000..edfe6a7e --- /dev/null +++ b/folly/Try.h @@ -0,0 +1,423 @@ +/* + * Copyright 2016 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace folly { + +class TryException : public std::exception { + public: + explicit TryException(std::string message_arg) noexcept + : message(std::move(message_arg)) {} + + const char* what() const noexcept override { + return message.c_str(); + } + + bool operator==(const TryException& other) const noexcept { + return other.message == this->message; + } + + bool operator!=(const TryException& other) const noexcept { + return !(*this == other); + } + + protected: + std::string message; +}; + +class UsingUninitializedTry : public TryException { + public: + UsingUninitializedTry() noexcept : TryException("Using unitialized try") {} +}; + +/* + * Try is a wrapper that contains either an instance of T, an exception, or + * nothing. Exceptions are stored as exception_wrappers so that the user can + * minimize rethrows if so desired. + * + * To represent success or a captured exception, use Try. + */ +template +class Try { + static_assert(!std::is_reference::value, + "Try may not be used with reference types"); + + enum class Contains { + VALUE, + EXCEPTION, + NOTHING, + }; + + public: + /* + * The value type for the Try + */ + typedef T element_type; + + /* + * Construct an empty Try + */ + Try() : contains_(Contains::NOTHING) {} + + /* + * Construct a Try with a value by copy + * + * @param v The value to copy in + */ + explicit Try(const T& v) : contains_(Contains::VALUE), value_(v) {} + + /* + * Construct a Try with a value by move + * + * @param v The value to move in + */ + explicit Try(T&& v) : contains_(Contains::VALUE), value_(std::move(v)) {} + + /// Implicit conversion from Try to Try + template + /* implicit */ + Try(typename std::enable_if::value, + Try const&>::type t); + + /* + * Construct a Try with an exception_wrapper + * + * @param e The exception_wrapper + */ + explicit Try(exception_wrapper e) + : contains_(Contains::EXCEPTION), + e_(folly::make_unique(std::move(e))) {} + + /* + * DEPRECATED + * Construct a Try with an exception_pointer + * + * @param ep The exception_pointer. Will be rethrown. + */ + FOLLY_DEPRECATED("use Try(exception_wrapper)") + explicit Try(std::exception_ptr ep) + : contains_(Contains::EXCEPTION) { + try { + std::rethrow_exception(ep); + } catch (const std::exception& e) { + e_ = folly::make_unique(std::current_exception(), e); + } catch (...) { + e_ = folly::make_unique(std::current_exception()); + } + } + + // Move constructor + Try(Try&& t) noexcept; + // Move assigner + Try& operator=(Try&& t) noexcept; + + // Copy constructor + Try(const Try& t); + // Copy assigner + Try& operator=(const Try& t); + + ~Try(); + + /* + * Get a mutable reference to the contained value. If the Try contains an + * exception it will be rethrown. + * + * @returns mutable reference to the contained value + */ + T& value()&; + /* + * Get a rvalue reference to the contained value. If the Try contains an + * exception it will be rethrown. + * + * @returns rvalue reference to the contained value + */ + T&& value()&&; + /* + * Get a const reference to the contained value. If the Try contains an + * exception it will be rethrown. + * + * @returns const reference to the contained value + */ + const T& value() const&; + + /* + * If the Try contains an exception, rethrow it. Otherwise do nothing. + */ + void throwIfFailed() const; + + /* + * Const dereference operator. If the Try contains an exception it will be + * rethrown. + * + * @returns const reference to the contained value + */ + const T& operator*() const { return value(); } + /* + * Dereference operator. If the Try contains an exception it will be rethrown. + * + * @returns mutable reference to the contained value + */ + T& operator*() { return value(); } + + /* + * Const arrow operator. If the Try contains an exception it will be + * rethrown. + * + * @returns const reference to the contained value + */ + const T* operator->() const { return &value(); } + /* + * Arrow operator. If the Try contains an exception it will be rethrown. + * + * @returns mutable reference to the contained value + */ + T* operator->() { return &value(); } + + /* + * @returns True if the Try contains a value, false otherwise + */ + bool hasValue() const { return contains_ == Contains::VALUE; } + /* + * @returns True if the Try contains an exception, false otherwise + */ + bool hasException() const { return contains_ == Contains::EXCEPTION; } + + /* + * @returns True if the Try contains an exception of type Ex, false otherwise + */ + template + bool hasException() const { + return hasException() && e_->is_compatible_with(); + } + + exception_wrapper& exception() { + if (UNLIKELY(!hasException())) { + throw TryException("exception(): Try does not contain an exception"); + } + return *e_; + } + + const exception_wrapper& exception() const { + if (UNLIKELY(!hasException())) { + throw TryException("exception(): Try does not contain an exception"); + } + return *e_; + } + + /* + * If the Try contains an exception and it is of type Ex, execute func(Ex) + * + * @param func a function that takes a single parameter of type const Ex& + * + * @returns True if the Try held an Ex and func was executed, false otherwise + */ + template + bool withException(F func) const { + if (!hasException()) { + return false; + } + return e_->with_exception(std::move(func)); + } + + template + typename std::enable_if::type get() { + return std::forward(*this); + } + + template + typename std::enable_if::type get() { + return std::forward(value()); + } + + private: + Contains contains_; + union { + T value_; + std::unique_ptr e_; + }; +}; + +/* + * Specialization of Try for void value type. Encapsulates either success or an + * exception. + */ +template <> +class Try { + public: + /* + * The value type for the Try + */ + typedef void element_type; + + // Construct a Try holding a successful and void result + Try() : hasValue_(true) {} + + /* + * Construct a Try with an exception_wrapper + * + * @param e The exception_wrapper + */ + explicit Try(exception_wrapper e) + : hasValue_(false), + e_(folly::make_unique(std::move(e))) {} + + /* + * DEPRECATED + * Construct a Try with an exception_pointer + * + * @param ep The exception_pointer. Will be rethrown. + */ + FOLLY_DEPRECATED("use Try(exception_wrapper)") + explicit Try(std::exception_ptr ep) : hasValue_(false) { + try { + std::rethrow_exception(ep); + } catch (const std::exception& e) { + e_ = folly::make_unique(std::current_exception(), e); + } catch (...) { + e_ = folly::make_unique(std::current_exception()); + } + } + + // Copy assigner + Try& operator=(const Try& t) { + hasValue_ = t.hasValue_; + if (t.e_) { + e_ = folly::make_unique(*t.e_); + } + return *this; + } + // Copy constructor + Try(const Try& t) { + *this = t; + } + + // If the Try contains an exception, throws it + void value() const { throwIfFailed(); } + // Dereference operator. If the Try contains an exception, throws it + void operator*() const { return value(); } + + // If the Try contains an exception, throws it + inline void throwIfFailed() const; + + // @returns False if the Try contains an exception, true otherwise + bool hasValue() const { return hasValue_; } + // @returns True if the Try contains an exception, false otherwise + bool hasException() const { return !hasValue_; } + + // @returns True if the Try contains an exception of type Ex, false otherwise + template + bool hasException() const { + return hasException() && e_->is_compatible_with(); + } + + /* + * @throws TryException if the Try doesn't contain an exception + * + * @returns mutable reference to the exception contained by this Try + */ + exception_wrapper& exception() { + if (UNLIKELY(!hasException())) { + throw TryException("exception(): Try does not contain an exception"); + } + return *e_; + } + + const exception_wrapper& exception() const { + if (UNLIKELY(!hasException())) { + throw TryException("exception(): Try does not contain an exception"); + } + return *e_; + } + + /* + * If the Try contains an exception and it is of type Ex, execute func(Ex) + * + * @param func a function that takes a single parameter of type const Ex& + * + * @returns True if the Try held an Ex and func was executed, false otherwise + */ + template + bool withException(F func) const { + if (!hasException()) { + return false; + } + return e_->with_exception(std::move(func)); + } + + template + R get() { + return std::forward(*this); + } + + private: + bool hasValue_; + std::unique_ptr e_{nullptr}; +}; + +/* + * Extracts value from try and returns it. Throws if try contained an exception. + * + * @param t Try to extract value from + * + * @returns value contained in t + */ +template +T moveFromTry(Try& t); + +/* + * Throws if try contained an exception. + * + * @param t Try to move from + */ +void moveFromTry(Try& t); + +/* + * @param f a function to execute and capture the result of (value or exception) + * + * @returns Try holding the result of f + */ +template +typename std::enable_if< + !std::is_same::type, void>::value, + Try::type>>::type +makeTryWith(F&& f); + +/* + * Specialization of makeTryWith for void return + * + * @param f a function to execute and capture the result of + * + * @returns Try holding the result of f + */ +template +typename std::enable_if< + std::is_same::type, void>::value, + Try>::type +makeTryWith(F&& f); + +} // folly + +#include diff --git a/folly/fibers/AddTasks.h b/folly/fibers/AddTasks.h index 9e65fcce..63785eaf 100644 --- a/folly/fibers/AddTasks.h +++ b/folly/fibers/AddTasks.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace folly { namespace fibers { diff --git a/folly/fibers/FiberManager-inl.h b/folly/fibers/FiberManager-inl.h index 6b4e94a1..0e14525d 100644 --- a/folly/fibers/FiberManager-inl.h +++ b/folly/fibers/FiberManager-inl.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include namespace folly { namespace fibers { diff --git a/folly/fibers/FiberManager.h b/folly/fibers/FiberManager.h index a617dd6b..a2474b62 100644 --- a/folly/fibers/FiberManager.h +++ b/folly/fibers/FiberManager.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff --git a/folly/fibers/Promise.h b/folly/fibers/Promise.h index 807898ef..fde863da 100644 --- a/folly/fibers/Promise.h +++ b/folly/fibers/Promise.h @@ -16,7 +16,7 @@ #pragma once #include -#include +#include namespace folly { namespace fibers { diff --git a/folly/futures/Future.h b/folly/futures/Future.h index 990f2990..c3249fde 100644 --- a/folly/futures/Future.h +++ b/folly/futures/Future.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/folly/futures/Promise.h b/folly/futures/Promise.h index 379ad5d6..b18f59b2 100644 --- a/folly/futures/Promise.h +++ b/folly/futures/Promise.h @@ -17,7 +17,7 @@ #pragma once #include -#include +#include #include namespace folly { diff --git a/folly/futures/README.md b/folly/futures/README.md index 1a9e07fd..1af0945d 100644 --- a/folly/futures/README.md +++ b/folly/futures/README.md @@ -259,7 +259,7 @@ Although inspired by the C++11 std::future interface, it is not a drop-in replac

That then() method on futures is the real bread and butter of Futures code. It allows you to provide a callback which will be executed when that Future is complete. Note that while we fulfill the promise after setting the callback here, those operations could be swapped. Setting a callback on an already completed future executes the callback immediately.

-

In this case, the callback takes a value directly. If the Future contained an exception, the callback will be passed over and the exception will be propagated to the resultant Future - more on that in a second. Your callback may also take a Try, which encapsulates either an exception or a value of its templated type.

+

In this case, the callback takes a value directly. If the Future contained an exception, the callback will be passed over and the exception will be propagated to the resultant Future - more on that in a second. Your callback may also take a Try, which encapsulates either an exception or a value of its templated type.

f.then([](Try<int> const& t){
   cout << t.value();
diff --git a/folly/futures/Try-inl.h b/folly/futures/Try-inl.h
deleted file mode 100644
index ba988e3d..00000000
--- a/folly/futures/Try-inl.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include 
-
-namespace folly {
-
-template 
-Try::Try(Try&& t) noexcept : contains_(t.contains_) {
-  if (contains_ == Contains::VALUE) {
-    new (&value_)T(std::move(t.value_));
-  } else if (contains_ == Contains::EXCEPTION) {
-    new (&e_)std::unique_ptr(std::move(t.e_));
-  }
-}
-
-template 
-template 
-Try::Try(typename std::enable_if::value,
-                                    Try const&>::type t)
-    : contains_(Contains::NOTHING) {
-  if (t.hasValue()) {
-    contains_ = Contains::VALUE;
-    new (&value_) T();
-  } else if (t.hasException()) {
-    contains_ = Contains::EXCEPTION;
-    new (&e_) std::unique_ptr(
-        folly::make_unique(t.exception()));
-  }
-}
-
-template 
-Try& Try::operator=(Try&& t) noexcept {
-  if (this == &t) {
-    return *this;
-  }
-
-  this->~Try();
-  contains_ = t.contains_;
-  if (contains_ == Contains::VALUE) {
-    new (&value_)T(std::move(t.value_));
-  } else if (contains_ == Contains::EXCEPTION) {
-    new (&e_)std::unique_ptr(std::move(t.e_));
-  }
-  return *this;
-}
-
-template 
-Try::Try(const Try& t) {
-  static_assert(
-      std::is_copy_constructible::value,
-      "T must be copyable for Try to be copyable");
-  contains_ = t.contains_;
-  if (contains_ == Contains::VALUE) {
-    new (&value_)T(t.value_);
-  } else if (contains_ == Contains::EXCEPTION) {
-    new (&e_)std::unique_ptr();
-    e_ = folly::make_unique(*(t.e_));
-  }
-}
-
-template 
-Try& Try::operator=(const Try& t) {
-  static_assert(
-      std::is_copy_constructible::value,
-      "T must be copyable for Try to be copyable");
-  this->~Try();
-  contains_ = t.contains_;
-  if (contains_ == Contains::VALUE) {
-    new (&value_)T(t.value_);
-  } else if (contains_ == Contains::EXCEPTION) {
-    new (&e_)std::unique_ptr();
-    e_ = folly::make_unique(*(t.e_));
-  }
-  return *this;
-}
-
-template 
-Try::~Try() {
-  if (LIKELY(contains_ == Contains::VALUE)) {
-    value_.~T();
-  } else if (UNLIKELY(contains_ == Contains::EXCEPTION)) {
-    e_.~unique_ptr();
-  }
-}
-
-template 
-T& Try::value() & {
-  throwIfFailed();
-  return value_;
-}
-
-template 
-T&& Try::value() && {
-  throwIfFailed();
-  return std::move(value_);
-}
-
-template 
-const T& Try::value() const & {
-  throwIfFailed();
-  return value_;
-}
-
-template 
-void Try::throwIfFailed() const {
-  if (contains_ != Contains::VALUE) {
-    if (contains_ == Contains::EXCEPTION) {
-      e_->throwException();
-    } else {
-      throw UsingUninitializedTry();
-    }
-  }
-}
-
-void Try::throwIfFailed() const {
-  if (!hasValue_) {
-    e_->throwException();
-  }
-}
-
-template 
-inline T moveFromTry(Try& t) {
-  return std::move(t.value());
-}
-
-inline void moveFromTry(Try& t) {
-  return t.value();
-}
-
-template 
-typename std::enable_if<
-  !std::is_same::type, void>::value,
-  Try::type>>::type
-makeTryWith(F&& f) {
-  typedef typename std::result_of::type ResultType;
-  try {
-    return Try(f());
-  } catch (std::exception& e) {
-    return Try(exception_wrapper(std::current_exception(), e));
-  } catch (...) {
-    return Try(exception_wrapper(std::current_exception()));
-  }
-}
-
-template 
-typename std::enable_if<
-  std::is_same::type, void>::value,
-  Try>::type
-makeTryWith(F&& f) {
-  try {
-    f();
-    return Try();
-  } catch (std::exception& e) {
-    return Try(exception_wrapper(std::current_exception(), e));
-  } catch (...) {
-    return Try(exception_wrapper(std::current_exception()));
-  }
-}
-
-} // folly
diff --git a/folly/futures/Try.h b/folly/futures/Try.h
deleted file mode 100644
index ab37a596..00000000
--- a/folly/futures/Try.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-namespace folly {
-
-class TryException : public std::exception {
- public:
-  explicit TryException(std::string message_arg) noexcept
-      : message(std::move(message_arg)) {}
-
-  const char* what() const noexcept override {
-    return message.c_str();
-  }
-
-  bool operator==(const TryException& other) const noexcept {
-    return other.message == this->message;
-  }
-
-  bool operator!=(const TryException& other) const noexcept {
-    return !(*this == other);
-  }
-
- protected:
-  std::string message;
-};
-
-class UsingUninitializedTry : public TryException {
- public:
-  UsingUninitializedTry() noexcept : TryException("Using unitialized try") {}
-};
-
-/*
- * Try is a wrapper that contains either an instance of T, an exception, or
- * nothing. Exceptions are stored as exception_wrappers so that the user can
- * minimize rethrows if so desired.
- *
- * To represent success or a captured exception, use Try.
- */
-template 
-class Try {
-  static_assert(!std::is_reference::value,
-                "Try may not be used with reference types");
-
-  enum class Contains {
-    VALUE,
-    EXCEPTION,
-    NOTHING,
-  };
-
- public:
-  /*
-   * The value type for the Try
-   */
-  typedef T element_type;
-
-  /*
-   * Construct an empty Try
-   */
-  Try() : contains_(Contains::NOTHING) {}
-
-  /*
-   * Construct a Try with a value by copy
-   *
-   * @param v The value to copy in
-   */
-  explicit Try(const T& v) : contains_(Contains::VALUE), value_(v) {}
-
-  /*
-   * Construct a Try with a value by move
-   *
-   * @param v The value to move in
-   */
-  explicit Try(T&& v) : contains_(Contains::VALUE), value_(std::move(v)) {}
-
-  /// Implicit conversion from Try to Try
-  template 
-  /* implicit */
-  Try(typename std::enable_if::value,
-                              Try const&>::type t);
-
-  /*
-   * Construct a Try with an exception_wrapper
-   *
-   * @param e The exception_wrapper
-   */
-  explicit Try(exception_wrapper e)
-    : contains_(Contains::EXCEPTION),
-      e_(folly::make_unique(std::move(e))) {}
-
-  /*
-   * DEPRECATED
-   * Construct a Try with an exception_pointer
-   *
-   * @param ep The exception_pointer. Will be rethrown.
-   */
-  FOLLY_DEPRECATED("use Try(exception_wrapper)")
-  explicit Try(std::exception_ptr ep)
-    : contains_(Contains::EXCEPTION) {
-    try {
-      std::rethrow_exception(ep);
-    } catch (const std::exception& e) {
-      e_ = folly::make_unique(std::current_exception(), e);
-    } catch (...) {
-      e_ = folly::make_unique(std::current_exception());
-    }
-  }
-
-  // Move constructor
-  Try(Try&& t) noexcept;
-  // Move assigner
-  Try& operator=(Try&& t) noexcept;
-
-  // Copy constructor
-  Try(const Try& t);
-  // Copy assigner
-  Try& operator=(const Try& t);
-
-  ~Try();
-
-  /*
-   * Get a mutable reference to the contained value. If the Try contains an
-   * exception it will be rethrown.
-   *
-   * @returns mutable reference to the contained value
-   */
-  T& value()&;
-  /*
-   * Get a rvalue reference to the contained value. If the Try contains an
-   * exception it will be rethrown.
-   *
-   * @returns rvalue reference to the contained value
-   */
-  T&& value()&&;
-  /*
-   * Get a const reference to the contained value. If the Try contains an
-   * exception it will be rethrown.
-   *
-   * @returns const reference to the contained value
-   */
-  const T& value() const&;
-
-  /*
-   * If the Try contains an exception, rethrow it. Otherwise do nothing.
-   */
-  void throwIfFailed() const;
-
-  /*
-   * Const dereference operator. If the Try contains an exception it will be
-   * rethrown.
-   *
-   * @returns const reference to the contained value
-   */
-  const T& operator*() const { return value(); }
-  /*
-   * Dereference operator. If the Try contains an exception it will be rethrown.
-   *
-   * @returns mutable reference to the contained value
-   */
-  T& operator*() { return value(); }
-
-  /*
-   * Const arrow operator. If the Try contains an exception it will be
-   * rethrown.
-   *
-   * @returns const reference to the contained value
-   */
-  const T* operator->() const { return &value(); }
-  /*
-   * Arrow operator. If the Try contains an exception it will be rethrown.
-   *
-   * @returns mutable reference to the contained value
-   */
-  T* operator->() { return &value(); }
-
-  /*
-   * @returns True if the Try contains a value, false otherwise
-   */
-  bool hasValue() const { return contains_ == Contains::VALUE; }
-  /*
-   * @returns True if the Try contains an exception, false otherwise
-   */
-  bool hasException() const { return contains_ == Contains::EXCEPTION; }
-
-  /*
-   * @returns True if the Try contains an exception of type Ex, false otherwise
-   */
-  template 
-  bool hasException() const {
-    return hasException() && e_->is_compatible_with();
-  }
-
-  exception_wrapper& exception() {
-    if (UNLIKELY(!hasException())) {
-      throw TryException("exception(): Try does not contain an exception");
-    }
-    return *e_;
-  }
-
-  const exception_wrapper& exception() const {
-    if (UNLIKELY(!hasException())) {
-      throw TryException("exception(): Try does not contain an exception");
-    }
-    return *e_;
-  }
-
-  /*
-   * If the Try contains an exception and it is of type Ex, execute func(Ex)
-   *
-   * @param func a function that takes a single parameter of type const Ex&
-   *
-   * @returns True if the Try held an Ex and func was executed, false otherwise
-   */
-  template 
-  bool withException(F func) const {
-    if (!hasException()) {
-      return false;
-    }
-    return e_->with_exception(std::move(func));
-  }
-
-  template 
-  typename std::enable_if::type get() {
-    return std::forward(*this);
-  }
-
-  template 
-  typename std::enable_if::type get() {
-    return std::forward(value());
-  }
-
- private:
-  Contains contains_;
-  union {
-    T value_;
-    std::unique_ptr e_;
-  };
-};
-
-/*
- * Specialization of Try for void value type. Encapsulates either success or an
- * exception.
- */
-template <>
-class Try {
- public:
-  /*
-   * The value type for the Try
-   */
-  typedef void element_type;
-
-  // Construct a Try holding a successful and void result
-  Try() : hasValue_(true) {}
-
-  /*
-   * Construct a Try with an exception_wrapper
-   *
-   * @param e The exception_wrapper
-   */
-  explicit Try(exception_wrapper e)
-    : hasValue_(false),
-      e_(folly::make_unique(std::move(e))) {}
-
-  /*
-   * DEPRECATED
-   * Construct a Try with an exception_pointer
-   *
-   * @param ep The exception_pointer. Will be rethrown.
-   */
-  FOLLY_DEPRECATED("use Try(exception_wrapper)")
-  explicit Try(std::exception_ptr ep) : hasValue_(false) {
-    try {
-      std::rethrow_exception(ep);
-    } catch (const std::exception& e) {
-      e_ = folly::make_unique(std::current_exception(), e);
-    } catch (...) {
-      e_ = folly::make_unique(std::current_exception());
-    }
-  }
-
-  // Copy assigner
-  Try& operator=(const Try& t) {
-    hasValue_ = t.hasValue_;
-    if (t.e_) {
-      e_ = folly::make_unique(*t.e_);
-    }
-    return *this;
-  }
-  // Copy constructor
-  Try(const Try& t) {
-    *this = t;
-  }
-
-  // If the Try contains an exception, throws it
-  void value() const { throwIfFailed(); }
-  // Dereference operator. If the Try contains an exception, throws it
-  void operator*() const { return value(); }
-
-  // If the Try contains an exception, throws it
-  inline void throwIfFailed() const;
-
-  // @returns False if the Try contains an exception, true otherwise
-  bool hasValue() const { return hasValue_; }
-  // @returns True if the Try contains an exception, false otherwise
-  bool hasException() const { return !hasValue_; }
-
-  // @returns True if the Try contains an exception of type Ex, false otherwise
-  template 
-  bool hasException() const {
-    return hasException() && e_->is_compatible_with();
-  }
-
-  /*
-   * @throws TryException if the Try doesn't contain an exception
-   *
-   * @returns mutable reference to the exception contained by this Try
-   */
-  exception_wrapper& exception() {
-    if (UNLIKELY(!hasException())) {
-      throw TryException("exception(): Try does not contain an exception");
-    }
-    return *e_;
-  }
-
-  const exception_wrapper& exception() const {
-    if (UNLIKELY(!hasException())) {
-      throw TryException("exception(): Try does not contain an exception");
-    }
-    return *e_;
-  }
-
-  /*
-   * If the Try contains an exception and it is of type Ex, execute func(Ex)
-   *
-   * @param func a function that takes a single parameter of type const Ex&
-   *
-   * @returns True if the Try held an Ex and func was executed, false otherwise
-   */
-  template 
-  bool withException(F func) const {
-    if (!hasException()) {
-      return false;
-    }
-    return e_->with_exception(std::move(func));
-  }
-
-  template 
-  R get() {
-    return std::forward(*this);
-  }
-
- private:
-  bool hasValue_;
-  std::unique_ptr e_{nullptr};
-};
-
-/*
- * Extracts value from try and returns it. Throws if try contained an exception.
- *
- * @param t Try to extract value from
- *
- * @returns value contained in t
- */
-template 
-T moveFromTry(Try& t);
-
-/*
- * Throws if try contained an exception.
- *
- * @param t Try to move from
- */
-void moveFromTry(Try& t);
-
-/*
- * @param f a function to execute and capture the result of (value or exception)
- *
- * @returns Try holding the result of f
- */
-template 
-typename std::enable_if<
-  !std::is_same::type, void>::value,
-  Try::type>>::type
-makeTryWith(F&& f);
-
-/*
- * Specialization of makeTryWith for void return
- *
- * @param f a function to execute and capture the result of
- *
- * @returns Try holding the result of f
- */
-template 
-typename std::enable_if<
-  std::is_same::type, void>::value,
-  Try>::type
-makeTryWith(F&& f);
-
-} // folly
-
-#include 
diff --git a/folly/futures/detail/Core.h b/folly/futures/detail/Core.h
index d3dba861..a6ac6109 100644
--- a/folly/futures/detail/Core.h
+++ b/folly/futures/detail/Core.h
@@ -27,7 +27,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 #include 
diff --git a/folly/futures/test/HeaderCompileTest.cpp b/folly/futures/test/HeaderCompileTest.cpp
index cbee3d04..ae2e5ded 100644
--- a/folly/futures/test/HeaderCompileTest.cpp
+++ b/folly/futures/test/HeaderCompileTest.cpp
@@ -18,7 +18,7 @@
 
 // amazing what things can go wrong if you include things in an unexpected
 // order.
-#include 
+#include 
 #include 
 #include 
 
diff --git a/folly/futures/test/TryTest.cpp b/folly/futures/test/TryTest.cpp
deleted file mode 100644
index 899db525..00000000
--- a/folly/futures/test/TryTest.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2016 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include 
-
-#include 
-#include 
-
-using namespace folly;
-
-TEST(Try, basic) {
-  class A {
-   public:
-    A(int x) : x_(x) {}
-
-    int x() const {
-      return x_;
-    }
-   private:
-    int x_;
-  };
-
-  A a(5);
-  Try t_a(std::move(a));
-
-  Try t_void;
-
-  EXPECT_EQ(5, t_a.value().x());
-}
-
-// Make sure we can copy Trys for copyable types
-TEST(Try, copy) {
-  Try t;
-  auto t2 = t;
-}
-
-// But don't choke on move-only types
-TEST(Try, moveOnly) {
-  Try> t;
-  std::vector>> v;
-  v.reserve(10);
-}
-
-TEST(Try, makeTryWith) {
-  auto func = []() {
-    return folly::make_unique(1);
-  };
-
-  auto result = makeTryWith(func);
-  EXPECT_TRUE(result.hasValue());
-  EXPECT_EQ(*result.value(), 1);
-}
-
-TEST(Try, makeTryWithThrow) {
-  auto func = []() {
-    throw std::runtime_error("Runtime");
-    return folly::make_unique(1);
-  };
-
-  auto result = makeTryWith(func);
-  EXPECT_TRUE(result.hasException());
-}
-
-TEST(Try, makeTryWithVoid) {
-  auto func = []() {
-    return;
-  };
-
-  auto result = makeTryWith(func);
-  EXPECT_TRUE(result.hasValue());
-}
-
-TEST(Try, makeTryWithVoidThrow) {
-  auto func = []() {
-    throw std::runtime_error("Runtime");
-    return;
-  };
-
-  auto result = makeTryWith(func);
-  EXPECT_TRUE(result.hasException());
-}
diff --git a/folly/test/Makefile.am b/folly/test/Makefile.am
index 9932fe61..4d000a9a 100644
--- a/folly/test/Makefile.am
+++ b/folly/test/Makefile.am
@@ -215,6 +215,10 @@ indestructible_test_SOURCES = IndestructibleTest.cpp
 indestructible_test_LDADD = libfollytestmain.la
 TESTS += indestructible_test
 
+try_test_SOURCES = TryTest.cpp
+try_test_LDADD = libfollytestmain.la
+TESTS += try_test
+
 unit_test_SOURCES = UnitTest.cpp
 unit_test_LDADD = libfollytestmain.la
 TESTS += unit_test
@@ -244,7 +248,6 @@ futures_test_SOURCES = \
     ../futures/test/ThenTest.cpp \
     ../futures/test/TimekeeperTest.cpp \
     ../futures/test/TimesTest.cpp \
-    ../futures/test/TryTest.cpp \
     ../futures/test/UnwrapTest.cpp \
     ../futures/test/ViaTest.cpp \
     ../futures/test/WaitTest.cpp \
diff --git a/folly/test/TryTest.cpp b/folly/test/TryTest.cpp
new file mode 100644
index 00000000..e1f2c4e9
--- /dev/null
+++ b/folly/test/TryTest.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include 
+
+#include 
+#include 
+
+using namespace folly;
+
+TEST(Try, basic) {
+  class A {
+   public:
+    A(int x) : x_(x) {}
+
+    int x() const {
+      return x_;
+    }
+   private:
+    int x_;
+  };
+
+  A a(5);
+  Try t_a(std::move(a));
+
+  Try t_void;
+
+  EXPECT_EQ(5, t_a.value().x());
+}
+
+// Make sure we can copy Trys for copyable types
+TEST(Try, copy) {
+  Try t;
+  auto t2 = t;
+}
+
+// But don't choke on move-only types
+TEST(Try, moveOnly) {
+  Try> t;
+  std::vector>> v;
+  v.reserve(10);
+}
+
+TEST(Try, makeTryWith) {
+  auto func = []() {
+    return folly::make_unique(1);
+  };
+
+  auto result = makeTryWith(func);
+  EXPECT_TRUE(result.hasValue());
+  EXPECT_EQ(*result.value(), 1);
+}
+
+TEST(Try, makeTryWithThrow) {
+  auto func = []() {
+    throw std::runtime_error("Runtime");
+    return folly::make_unique(1);
+  };
+
+  auto result = makeTryWith(func);
+  EXPECT_TRUE(result.hasException());
+}
+
+TEST(Try, makeTryWithVoid) {
+  auto func = []() {
+    return;
+  };
+
+  auto result = makeTryWith(func);
+  EXPECT_TRUE(result.hasValue());
+}
+
+TEST(Try, makeTryWithVoidThrow) {
+  auto func = []() {
+    throw std::runtime_error("Runtime");
+    return;
+  };
+
+  auto result = makeTryWith(func);
+  EXPECT_TRUE(result.hasException());
+}