From: Eric Niebler Date: Mon, 15 Aug 2016 17:20:25 +0000 (-0700) Subject: Add folly::Expected, an alternative to exceptions for non-throwing APIs that can... X-Git-Tag: v2016.08.22.00~40 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=4d932ecc53c7a72267179e58eeed7ec56eb7dc53;p=folly.git Add folly::Expected, an alternative to exceptions for non-throwing APIs that can fail. Summary: Expected is like an Optional with extra state for reporting //why// the Expected is empty. Something like it is currently under review for inclusion in the C++ standard [1], and Andrei Alexandrescu has spoken about it [2]. It corresponds to the Either Monad in Haskell, where it is used as a return type of an API that has more than one failure mode. By adding folly::Expected, we get a way to implement non-throwing APIs with a consistent and composable interface. [^1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4015.pdf [^2]: https://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C Reviewed By: mhx Differential Revision: D3522501 fbshipit-source-id: 48b8ea2dfbd0769f26ec84d2d52fd41db75dc05a --- diff --git a/folly/Expected.h b/folly/Expected.h new file mode 100644 index 00000000..cde4a04b --- /dev/null +++ b/folly/Expected.h @@ -0,0 +1,1342 @@ +/* + * 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. + */ + +/** + * Like folly::Optional, but can store a value *or* and error. + * + * @author Eric Niebler (eniebler@fb.com) + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // for construct_in_place_t +#include + +#define FOLLY_EXPECTED_ID(X) FB_CONCATENATE(FB_CONCATENATE(Folly, X), __LINE__) + +#define FOLLY_REQUIRES_IMPL(...) \ + bool FOLLY_EXPECTED_ID(Requires) = false, \ + typename std::enable_if< \ + (FOLLY_EXPECTED_ID(Requires) || static_cast(__VA_ARGS__)), \ + int>::type = 0 + +#define FOLLY_REQUIRES_TRAILING(...) , FOLLY_REQUIRES_IMPL(__VA_ARGS__) + +#define FOLLY_REQUIRES(...) template + +/** + * gcc-4.7 warns about use of uninitialized memory around the use of storage_ + * even though this is explicitly initialized at each point. + */ +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif // __GNUC__ + +namespace folly { + +/** + * Forward declarations + */ +template +class Unexpected; + +template +constexpr Unexpected::type> makeUnexpected(Error&&); + +template +class Expected; + +template +constexpr Expected::type, Error> makeExpected( + Value&&); + +/** + * Alias for an Expected type's assiciated value_type + */ +template +using ExpectedValueType = + typename std::remove_reference::type::value_type; + +/** + * Alias for an Expected type's assiciated error_type + */ +template +using ExpectedErrorType = + typename std::remove_reference::type::error_type; + +// Details... +namespace expected_detail { +template