/* * 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 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())); } } template std::tuple unwrapTryTuple(std::tuple...>&& ts) { return detail::TryTuple::unwrap( std::forward...>>(ts)); } } // folly