aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/expected-lite
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-10-18 20:31:38 +0300
committerGitHub <noreply@github.com>2024-10-18 20:31:38 +0300
commit2a74bac2d2d3bccb4e10120f1ead805640ec9dd0 (patch)
tree047e4818ced5aaf73f58517629e5260b5291f9f0 /contrib/restricted/expected-lite
parent2d9656823e9521d8c29ea4c9a1d0eab78391abfc (diff)
parent3d834a1923bbf9403cd4a448e7f32b670aa4124f (diff)
downloadydb-2a74bac2d2d3bccb4e10120f1ead805640ec9dd0.tar.gz
Merge pull request #10502 from ydb-platform/mergelibs-241016-1210
Library import 241016-1210
Diffstat (limited to 'contrib/restricted/expected-lite')
-rw-r--r--contrib/restricted/expected-lite/.yandex_meta/devtools.copyrights.report41
-rw-r--r--contrib/restricted/expected-lite/.yandex_meta/devtools.licenses.report79
-rw-r--r--contrib/restricted/expected-lite/.yandex_meta/licenses.list.txt62
-rw-r--r--contrib/restricted/expected-lite/CHANGES.txt5
-rw-r--r--contrib/restricted/expected-lite/LICENSE.txt23
-rw-r--r--contrib/restricted/expected-lite/README.md506
-rw-r--r--contrib/restricted/expected-lite/include/nonstd/expected.hpp3555
-rw-r--r--contrib/restricted/expected-lite/ya.make13
8 files changed, 4284 insertions, 0 deletions
diff --git a/contrib/restricted/expected-lite/.yandex_meta/devtools.copyrights.report b/contrib/restricted/expected-lite/.yandex_meta/devtools.copyrights.report
new file mode 100644
index 0000000000..8f9a274352
--- /dev/null
+++ b/contrib/restricted/expected-lite/.yandex_meta/devtools.copyrights.report
@@ -0,0 +1,41 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP COPYRIGHT_SERVICE_LABEL 81e2e1bd273033f7a382ceaf46d6ae84
+BELONGS ya.make
+ License text:
+ // Copyright (C) 2016-2020 Martin Moene.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ include/nonstd/expected.hpp [3:3]
diff --git a/contrib/restricted/expected-lite/.yandex_meta/devtools.licenses.report b/contrib/restricted/expected-lite/.yandex_meta/devtools.licenses.report
new file mode 100644
index 0000000000..e7b3d6ba44
--- /dev/null
+++ b/contrib/restricted/expected-lite/.yandex_meta/devtools.licenses.report
@@ -0,0 +1,79 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+SKIP IPL-1.0 18358e6da236a2ee9e6e43715ed951f6
+BELONGS ya.make
+ # Not a license
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: IPL-1.0
+ Score : 57.14
+ Match type : REFERENCE
+ Links : http://www.opensource.org/licenses/ibmpl.php, https://spdx.org/licenses/IPL-1.0
+ Files with this license:
+ README.md [3:3]
+
+KEEP BSL-1.0 2c7a3fa82e66676005cd4ee2608fd7d2
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ LICENSE.txt [1:23]
+
+KEEP BSL-1.0 73a2516db620f6413502ee77bdb4af88
+BELONGS ya.make
+ License text:
+ *expected lite* is distributed under the [Boost Software License](https://github.com/martinmoene/XXXX-lite/blob/master/LICENSE.txt).
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ README.md [76:76]
+
+KEEP BSL-1.0 cccf0dd010adef3878bb56734414eca6
+BELONGS ya.make
+FILE_INCLUDE LICENSE.txt found in files: include/nonstd/expected.hpp at line 6
+ License text:
+ // Distributed under the Boost Software License, Version 1.0.
+ // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ Scancode info:
+ Original SPDX id: BSL-1.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0
+ Files with this license:
+ include/nonstd/expected.hpp [5:6]
diff --git a/contrib/restricted/expected-lite/.yandex_meta/licenses.list.txt b/contrib/restricted/expected-lite/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..481545b760
--- /dev/null
+++ b/contrib/restricted/expected-lite/.yandex_meta/licenses.list.txt
@@ -0,0 +1,62 @@
+====================BSL-1.0====================
+*expected lite* is distributed under the [Boost Software License](https://github.com/martinmoene/XXXX-lite/blob/master/LICENSE.txt).
+
+
+====================BSL-1.0====================
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+====================BSL-1.0====================
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+====================COPYRIGHT====================
+// Copyright (C) 2016-2020 Martin Moene.
+
+
+====================File: LICENSE.txt====================
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/contrib/restricted/expected-lite/CHANGES.txt b/contrib/restricted/expected-lite/CHANGES.txt
new file mode 100644
index 0000000000..9c18a5702f
--- /dev/null
+++ b/contrib/restricted/expected-lite/CHANGES.txt
@@ -0,0 +1,5 @@
+Changes for expected lite
+
+version 0.0 2016-03-13
+
+- Initial code commit.
diff --git a/contrib/restricted/expected-lite/LICENSE.txt b/contrib/restricted/expected-lite/LICENSE.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/contrib/restricted/expected-lite/LICENSE.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/contrib/restricted/expected-lite/README.md b/contrib/restricted/expected-lite/README.md
new file mode 100644
index 0000000000..bbef2e20f8
--- /dev/null
+++ b/contrib/restricted/expected-lite/README.md
@@ -0,0 +1,506 @@
+# expected lite: expected objects for C++11 and later
+
+[![Language](https://img.shields.io/badge/C%2B%2B-11-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization) [![License](https://img.shields.io/badge/license-BSL-blue.svg)](https://opensource.org/licenses/BSL-1.0) [![Build Status](https://github.com/martinmoene/expected-lite/actions/workflows/ci.yml/badge.svg)](https://github.com/martinmoene/expected-lite/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/sle31w7obrm8lhe1?svg=true)](https://ci.appveyor.com/project/martinmoene/expected-lite) [![Version](https://badge.fury.io/gh/martinmoene%2Fexpected-lite.svg)](https://github.com/martinmoene/expected-lite/releases) [![download](https://img.shields.io/badge/latest-download-blue.svg)](https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp) [![Conan](https://img.shields.io/badge/on-conan-blue.svg)](https://conan.io/center/expected-lite) [![Vcpkg](https://img.shields.io/badge/on-vcpkg-blue.svg)](https://vcpkg.link/ports/expected-lite) [![Try it online](https://img.shields.io/badge/on-wandbox-blue.svg)](https://wandbox.org/permlink/MnnwqOtE8ZQ4rRsv) [![Try it on godbolt online](https://img.shields.io/badge/on-godbolt-blue.svg)](https://godbolt.org/z/9BuMZx)
+
+*expected lite* is a single-file header-only library for objects that either represent a valid value or an error that you can pass by value. It is intended for use with C++11 and later. The library is based on the [std:&#58;expected](http://wg21.link/p0323) proposal [1] .
+
+**Contents**
+- [Example usage](#example-usage)
+- [In a nutshell](#in-a-nutshell)
+- [License](#license)
+- [Dependencies](#dependencies)
+- [Installation](#installation)
+- [Synopsis](#synopsis)
+- [Comparison with like types](#comparison)
+- [Reported to work with](#reported-to-work-with)
+- [Implementation notes](#implementation-notes)
+- [Other implementations of expected](#other-implementations-of-expected)
+- [Notes and references](#notes-and-references)
+- [Appendix](#appendix)
+
+## Example usage
+
+```Cpp
+#include "nonstd/expected.hpp"
+
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+using namespace nonstd;
+using namespace std::literals;
+
+auto to_int( char const * const text ) -> expected<int, std::string>
+{
+ char * pos = nullptr;
+ auto value = strtol( text, &pos, 0 );
+
+ if ( pos != text ) return value;
+ else return make_unexpected( "'"s + text + "' isn't a number" );
+}
+
+int main( int argc, char * argv[] )
+{
+ auto text = argc > 1 ? argv[1] : "42";
+
+ auto ei = to_int( text );
+
+ if ( ei ) std::cout << "'" << text << "' is " << *ei << ", ";
+ else std::cout << "Error: " << ei.error();
+}
+```
+
+### Compile and run
+
+```
+prompt> g++ -std=c++14 -Wall -I../include -o 01-basic.exe 01-basic.cpp && 01-basic.exe 123 && 01-basic.exe abc
+'123' is 123, Error: 'abc' isn't a number
+```
+
+## In a nutshell
+
+**expected lite** is a single-file header-only library to represent value objects that either contain a valid value or an error. The library is a partly implementation of the proposal for [std:&#58;expected](http://wg21.link/p0323) [1,2,3] for use with C++11 and later.
+
+**Some Features and properties of expected lite** are ease of installation (single header), default and explicit construction of an expected, construction and assignment from a value that is convertible to the underlying type, copy- and move-construction and copy- and move-assignment from another expected of the same type, testing for the presence of a value, operators for unchecked access to the value or the error (pointer or reference), value() and value_or() for checked access to the value, relational operators, swap() and various factory functions.
+
+Version 0.7.0 introduces the monadic operations of propsoal [p2505](http://wg21.link/p2505).
+
+*expected lite* shares the approach to in-place tags with [any-lite](https://github.com/martinmoene/any-lite), [optional-lite](https://github.com/martinmoene/optional-lite) and with [variant-lite](https://github.com/martinmoene/variant-lite) and these libraries can be used together.
+
+**Not provided** are reference-type expecteds. *expected lite* doesn't honour triviality of value and error types. *expected lite* doesn't handle overloaded *address of* operators.
+
+For more examples, see [1].
+
+## License
+
+*expected lite* is distributed under the [Boost Software License](https://github.com/martinmoene/XXXX-lite/blob/master/LICENSE.txt).
+
+## Dependencies
+
+*expected lite* has no other dependencies than the [C++ standard library](http://en.cppreference.com/w/cpp/header).
+
+## Installation
+
+*expected lite* is a single-file header-only library. Put `expected.hpp` directly into the project source tree or somewhere reachable from your project.
+
+## Synopsis
+
+**Contents**
+- [Configuration](#configuration)
+- [Types in namespace nonstd](#types-in-namespace-nonstd)
+- [Interface of expected](#interface-of-expected)
+- [Algorithms for expected](#algorithms-for-expected)
+- [Interface of unexpected_type](#interface-of-unexpected_type)
+- [Algorithms for unexpected_type](#algorithms-for-unexpected_type)
+
+### Configuration
+
+#### Tweak header
+
+If the compiler supports [`__has_include()`](https://en.cppreference.com/w/cpp/preprocessor/include), *expected lite* supports the [tweak header](https://vector-of-bool.github.io/2020/10/04/lib-configuration.html) mechanism. Provide your *tweak header* as `nonstd/expected.tweak.hpp` in a folder in the include-search-path. In the tweak header, provide definitions as documented below, like `#define expected_CPLUSPLUS 201103L`.
+
+#### Standard selection macro
+
+\-D<b>nsel\_CPLUSPLUS</b>=199711L
+Define this macro to override the auto-detection of the supported C++ standard, or if your compiler does not set the `__cplusplus` macro correctly.
+
+#### Select `std::expected` or `nonstd::expected`
+
+At default, *expected lite* uses `std::expected` if it is available and lets you use it via namespace `nonstd`. You can however override this default and explicitly request to use `std::expected` or expected lite's `nonstd::expected` as `nonstd::expected` via the following macros.
+
+-D<b>nsel\_CONFIG\_SELECT\_EXPECTED</b>=nsel_EXPECTED_DEFAULT
+Define this to `nsel_EXPECTED_STD` to select `std::expected` as `nonstd::expected`. Define this to `nsel_EXPECTED_NONSTD` to select `nonstd::expected` as `nonstd::expected`. Default is undefined, which has the same effect as defining to `nsel_EXPECTED_DEFAULT`.
+
+-D<b>nsel\_P0323R</b>=7 *(default)*
+Define this to the proposal revision number to control the presence and behavior of features (see tables). Default is 7 for the latest revision.
+
+#### Disable C++ exceptions
+
+-D<b>nsel\_CONFIG\_NO\_EXCEPTIONS</b>=0
+Define this to 1 if you want to compile without exceptions. If not defined, the header tries and detect if exceptions have been disabled (e.g. via `-fno-exceptions` or `/kernel`). Default determined in header.
+
+#### Enable SEH exceptions
+
+-D<b>nsel\_CONFIG\_NO\_EXCEPTIONS\_SEH</b>=0
+Define this to 1 or 0 to control the use of SEH when C++ exceptions are disabled (see above). If not defined, the header tries and detect if SEH is available if C++ exceptions have been disabled (e.g. via `-fno-exceptions` or `/kernel`). Default determined in header.
+
+#### Enable compilation errors
+
+\-D<b>nsel\_CONFIG\_CONFIRMS\_COMPILATION\_ERRORS</b>=0
+Define this macro to 1 to experience the by-design compile-time errors of the library in the test suite. Default is 0.
+
+#### Configure P2505 monadic operations
+
+By default, *expected lite* provides monadic operations as described in [P2505R5](http://wg21.link/p2505r5). You can disable these operations by defining the following macro.
+
+-D<b>nsel\_P2505R</b>=0
+
+You can use the R3 revision of P2505, which lacks `error_or`, and uses `remove_cvref` for transforms, by defining the following macro.
+
+-D<b>nsel\_P2505R</b>=3
+
+### Types in namespace nonstd
+
+| Purpose | Type | Note / Object |
+|-----------------|------|---------------|
+| Expected | template&lt;typename T, typename E = std::exception_ptr><br>class **expected**; | nsel_P0323 <= 2 |
+| Expected | template&lt;typename T, typename E><br>class **expected**; | nsel_P0323 > 2 |
+| Error type | template&lt;typename E><br>class **unexpected_type**; | &nbsp; |
+| Error type | template&lt;><br>class **unexpected_type**&lt;std::exception_ptr>; | nsel_P0323 <= 2 |
+| Error type | template&lt;typename E><br>class **unexpected**; | >= C++17 |
+| Traits | template&lt;typename E><br>struct **is_unexpected**; | nsel_P0323 <= 3 |
+| In-place value construction | struct **in_place_t**; | in_place_t in_place{}; |
+| In-place error construction | struct **in_place_unexpected_t**; | in_place_unexpected_t<br>unexpect{}; |
+| In-place error construction | struct **in_place_unexpected_t**; | in_place_unexpected_t<br>in_place_unexpected{}; |
+| Error reporting | class **bad_expected_access**; |&nbsp; |
+
+### Interface of expected
+
+| Kind | Method | Result |
+|--------------|-------------------------------------------------------------------------|--------|
+| Construction | [constexpr] **expected**() noexcept(...) | an object with default value |
+| &nbsp; | [constexpr] **expected**( expected const & other ) | initialize to contents of other |
+| &nbsp; | [constexpr] **expected**( expected && other ) | move contents from other |
+| &nbsp; | [constexpr] **expected**( value_type const & value ) | initialize to value |
+| &nbsp; | [constexpr] **expected**( value_type && value ) noexcept(...) | move from value |
+| &nbsp; | [constexpr] explicit **expected**( in_place_t, Args&&... args ) | construct value in-place from args |
+| &nbsp; | [constexpr] explicit **expected**( in_place_t,<br>&emsp;std::initializer_list&lt;U> il, Args&&... args ) | construct value in-place from args |
+| &nbsp; | [constexpr] **expected**( unexpected_type<E> const & error ) | initialize to error |
+| &nbsp; | [constexpr] **expected**( unexpected_type<E> && error ) | move from error |
+| &nbsp; | [constexpr] explicit **expected**( in_place_unexpected_t,<br>&emsp;Args&&... args ) | construct error in-place from args |
+| &nbsp; | [constexpr] explicit **expected**( in_place_unexpected_t,<br>&emsp;std::initializer_list&lt;U> il, Args&&... args )| construct error in-place from args |
+| Destruction | ~**expected**() | destruct current content |
+| Assignment | expected **operator=**( expected const & other ) | assign contents of other;<br>destruct current content, if any |
+| &nbsp; | expected & **operator=**( expected && other ) noexcept(...) | move contents of other |
+| &nbsp; | expected & **operator=**( U && v ) | move value from v |
+| &nbsp; | expected & **operator=**( unexpected_type<E> const & u ) | initialize to unexpected |
+| &nbsp; | expected & **operator=**( unexpected_type<E> && u ) | move from unexpected |
+| &nbsp; | template&lt;typename... Args><br>void **emplace**( Args &&... args ) | emplace from args |
+| &nbsp; | template&lt;typename U, typename... Args><br>void **emplace**( std::initializer_list&lt;U> il, Args &&... args ) | emplace from args |
+| Swap | void **swap**( expected & other ) noexcept | swap with other |
+| Observers | constexpr value_type const \* **operator->**() const | pointer to current content (const);<br>must contain value |
+| &nbsp; | value_type \* **operator->**() | pointer to current content (non-const);<br>must contain value |
+| &nbsp; | constexpr value_type const & **operator \***() const & | the current content (const ref);<br>must contain value |
+| &nbsp; | constexpr value_type && **operator \***() && | the current content (non-const ref);<br>must contain value |
+| &nbsp; | constexpr explicit operator **bool**() const noexcept | true if contains value |
+| &nbsp; | constexpr **has_value**() const noexcept | true if contains value |
+| &nbsp; | constexpr value_type const & **value**() const & | current content (const ref);<br>see [note 1](#note1) |
+| &nbsp; | value_type & **value**() & | current content (non-const ref);<br>see [note 1](#note1) |
+| &nbsp; | constexpr value_type && **value**() && | move from current content;<br>see [note 1](#note1) |
+| &nbsp; | constexpr error_type const & **error**() const & | current error (const ref);<br>must contain error |
+| &nbsp; | error_type & **error**() & | current error (non-const ref);<br>must contain error |
+| &nbsp; | constexpr error_type && **error**() && | move from current error;<br>must contain error |
+| &nbsp; | constexpr unexpected_type<E> **get_unexpected**() const | the error as unexpected&lt;>;<br>must contain error |
+| &nbsp; | template&lt;typename Ex><br>bool **has_exception**() const | true of contains exception (as base) |
+| &nbsp; | value_type **value_or**( U && v ) const & | value or move from v |
+| &nbsp; | value_type **value_or**( U && v ) && | move from value or move from v |
+| &nbsp; | constexpr error_type **error_or**( G && e ) const & | return current error or v [requires nsel_P2505R >= 4] |
+| &nbsp; | constexpr error_type **error_or**( G && e ) && | move from current error or from v [requires nsel_P2505R >=4] |
+| Monadic operations<br>(requires nsel_P2505R >= 3) | constexpr auto **and_then**( F && f ) & G| return f(value()) if has value, otherwise the error |
+| &nbsp; | constexpr auto **and_then**( F && f ) const & | return f(value()) if has value, otherwise the error |
+| &nbsp; | constexpr auto **and_then**( F && f ) && | return f(std::move(value())) if has value, otherwise the error |
+| &nbsp; | constexpr auto **and_then**( F && f ) const && | return f(std::move(value())) if has value, otherwise the error |
+| &nbsp; | constexpr auto **or_else**( F && f ) & | return the value, or f(error()) if there is no value |
+| &nbsp; | constexpr auto **or_else**( F && f ) const & | return the value, or f(error()) if there is no value |
+| &nbsp; | constexpr auto **or_else**( F && f ) && | return the value, or f(std::move(error())) if there is no value |
+| &nbsp; | constexpr auto **or_else**( F && f ) const && | return the value, or f(std::move(error())) if there is no value |
+| &nbsp; | constexpr auto **transform**( F && f ) & | return f(value()) wrapped if has value, otherwise the error |
+| &nbsp; | constexpr auto **transform**( F && f ) const & | return f(value()) wrapped if has value, otherwise the error |
+| &nbsp; | constexpr auto **transform**( F && f ) && | return f(std::move(value())) wrapped if has value, otherwise the error |
+| &nbsp; | constexpr auto **transform**( F && f ) const && | return f(std::move(value())) wrapped if has value, otherwise the error |
+| &nbsp; | constexpr auto **transform_error**( F && f ) & | return the value if has value, or f(error()) otherwise |
+| &nbsp; | constexpr auto **transform_error**( F && f ) const & | return the value if has value, or f(error()) otherwise |
+| &nbsp; | constexpr auto **transform_error**( F && f ) && | return the value if has value, or f(std::move(error())) otherwise |
+| &nbsp; | constexpr auto **transform_error**( F && f ) const && | return the value if has value, or f(std::move(error())) otherwise |
+| &nbsp; | ... | &nbsp; |
+
+<a id="note1"></a>Note 1: checked access: if no content, for std::exception_ptr rethrows error(), otherwise throws bad_expected_access(error()).
+
+### Algorithms for expected
+
+| Kind | Function |
+|---------------------------------|----------|
+| Comparison with expected | &nbsp; |
+| ==&ensp;!= | template&lt;typename T1, typename E1, typename T2, typename E2><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T1,E1> const & x,<br>&emsp;expected&lt;T2,E2> const & y ) |
+| Comparison with expected | nsel_P0323R <= 2 |
+| <&ensp;>&ensp;<=&ensp;>= | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T,E> const & x,<br>&emsp;expected&lt;T,E> const & y ) |
+| Comparison with unexpected_type | &nbsp; |
+| ==&ensp;!= | template&lt;typename T1, typename E1, typename E2><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T1,E1> const & x,<br>&emsp;unexpected_type&lt;E2> const & u ) |
+| &nbsp; | template&lt;typename T1, typename E1, typename E2><br>constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;E2> const & u,<br>&emsp;expected&lt;T1,E1> const & x ) |
+| Comparison with unexpected_type | nsel_P0323R <= 2 |
+| <&ensp;>&ensp;<=&ensp;>= | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T,E> const & x,<br>&emsp;unexpected_type&lt;E> const & u ) |
+| &nbsp; | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;E> const & u,<br>&emsp;expected&lt;T,E> const & x ) |
+| Comparison with T | &nbsp; |
+| ==&ensp;!= | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T,E> const & x,<br>&emsp;T const & v ) |
+| &nbsp; | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;T const & v,<br>&emsp;expected&lt;T,E> const & x ) |
+| Comparison with T | nsel_P0323R <= 2 |
+| <&ensp;>&ensp;<=&ensp;>= | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;expected&lt;T,E> const & x,<br>&emsp;T const & v ) |
+| &nbsp; | template&lt;typename T, typename E><br>constexpr bool operator ***op***(<br>&emsp;T const & v,<br>&emsp;expected&lt;T,E> const & x ) |
+| Specialized algorithms | &nbsp; |
+| Swap | template&lt;typename T, typename E><br>void **swap**(<br>&emsp;expected&lt;T,E> & x,<br>&emsp;expected&lt;T,E> & y )&emsp;noexcept( noexcept( x.swap(y) ) ) |
+| Make expected from | nsel_P0323R <= 3 |
+| &emsp;Value | template&lt;typename T><br>constexpr auto **make_expected**( T && v ) -><br>&emsp;expected< typename std::decay&lt;T>::type> |
+| &emsp;Nothing | auto **make_expected**() -> expected&lt;void> |
+| &emsp;Current exception | template&lt;typename T><br>constexpr auto **make_expected_from_current_exception**() -> expected&lt;T> |
+| &emsp;Exception | template&lt;typename T><br>auto **make_expected_from_exception**( std::exception_ptr v ) -> expected&lt;T>|
+| &emsp;Error | template&lt;typename T, typename E><br>constexpr auto **make_expected_from_error**( E e ) -><br>&emsp;expected&lt;T, typename std::decay&lt;E>::type> |
+| &emsp;Call | template&lt;typename F><br>auto **make_expected_from_call**( F f ) -><br>&emsp;expected< typename std::result_of&lt;F()>::type>|
+| &emsp;Call, void specialization | template&lt;typename F><br>auto **make_expected_from_call**( F f ) -> expected&lt;void> |
+
+### Interface of unexpected_type
+
+| Kind | Method | Result |
+|--------------|-----------------------------------------------------------|--------|
+| Construction | **unexpected_type**() = delete; | no default construction |
+| &nbsp; | constexpr explicit **unexpected_type**( E const & error ) | copy-constructed from an E |
+| &nbsp; | constexpr explicit **unexpected_type**( E && error ) | move-constructed from an E |
+| Observers | constexpr error_type const & **error**() const | can observe contained error |
+| &nbsp; | error_type & **error**() | can modify contained error |
+| deprecated | constexpr error_type const & **value**() const | can observe contained error |
+| deprecated | error_type & **value**() | can modify contained error |
+
+### Algorithms for unexpected_type
+
+| Kind | Function |
+|-------------------------------|----------|
+| Comparison with unexpected | &nbsp; |
+| ==&ensp;!= | template&lt;typename E><br>constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;E> const & x,<br>&emsp;unexpected_type&lt;E> const & y ) |
+| Comparison with unexpected | nsel_P0323R <= 2 |
+| <&ensp;>&ensp;<=&ensp;>= | template&lt;typename E><br>constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;E> const & x,<br>&emsp;unexpected_type&lt;E> const & y ) |
+| Comparison with exception_ptr | &nbsp; |
+| ==&ensp;!= | constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;std::exception_ptr> const & x,<br>&emsp;unexpected_type&lt;std::exception_ptr> const & y ) |
+| Comparison with exception_ptr | nsel_P0323R <= 2 |
+| <&ensp;>&ensp;<=&ensp;>= | constexpr bool operator ***op***(<br>&emsp;unexpected_type&lt;std::exception_ptr> const & x,<br>&emsp;unexpected_type&lt;std::exception_ptr> const & y ) |
+| Specialized algorithms | &nbsp; |
+| Make unexpected from | &nbsp; |
+| &emsp;Error | template&lt;typename E><br>[constexpr] auto **make_unexpected**( E && v) -><br>&emsp;unexpected_type< typename std::decay&lt;E>::type>|
+| Make unexpected from | nsel_P0323R <= 3 |
+| &emsp;Current exception | [constexpr] auto **make_unexpected_from_current_exception**() -><br>&emsp;unexpected_type< std::exception_ptr>|
+
+<a id="comparison"></a>
+## Comparison with like types
+
+|Feature |<br>std::pair|std:: optional |std:: expected |nonstd:: expected |Boost. Expected |Nonco expected |Andrei Expected |Hagan required |
+|----------------------|-------------|---------------|---------------|------------------|----------------|---------------|----------------|---------------|
+|More information | see [14] | see [5] | see [1] | this work | see [4] | see [7] | see [8] | see [13] |
+| | | | | | | | | |
+| C++03 | yes | no | no | no/not yet | no (union) | no | no | yes |
+| C++11 | yes | no | no | yes | yes | yes | yes | yes |
+| C++14 | yes | no | no | yes | yes | yes | yes | yes |
+| C++17 | yes | yes | no | yes | yes | yes | yes | yes |
+| | | | | | | | | |
+|DefaultConstructible | T param | yes | yes | yes | yes | no | no | no |
+|In-place construction | no | yes | yes | yes | yes | yes | no | no |
+|Literal type | yes | yes | yes | yes | yes | no | no | no |
+| | | | | | | | | |
+|Disengaged information| possible | no | yes | yes | yes | yes | yes | no |
+|Vary disengaged type | yes | no | yes | yes | yes | no | no | no |
+|Engaged nonuse throws | no | no | no | no | error_traits | no | no | yes |
+|Disengaged use throws | no | yes, value() | yes, value() | yes, value() | yes,<br>value()| yes,<br>get() | yes,<br>get() | n/a |
+| | | | | | | | | |
+|Proxy (rel.ops) | no | yes | yes | yes | yes | no | no | no |
+|References | no | yes | no/not yet | no/not yet | no/not yet | yes | no | no |
+|Chained visitor(s) | no | no | yes | yes | yes | no | no | no |
+
+Note 1: std:&#58;*experimental*:&#58;expected
+
+Note 2: sources for [Nonco expected](https://github.com/martinmoene/spike-expected/tree/master/nonco), [Andrei Expected](https://github.com/martinmoene/spike-expected/tree/master/alexandrescu) and [Hagan required](https://github.com/martinmoene/spike-expected/tree/master/hagan) can befound in the [spike-expected](https://github.com/martinmoene/spike-expected) repository.
+
+## Reported to work with
+
+TBD
+
+## Implementation notes
+
+TBD
+
+## Other implementations of expected
+
+- Simon Brand. [C++11/14/17 std::expected with functional-style extensions](https://github.com/TartanLlama/expected). Single-header.
+- Isabella Muerte. [MNMLSTC Core](https://github.com/mnmlstc/core) (C++11).
+- Vicente J. Botet Escriba. [stdmake's expected](https://github.com/viboes/std-make/tree/master/include/experimental/fundamental/v3/expected) (C++17).
+- Facebook. [ Folly's Expected.h](https://github.com/facebook/folly/blob/master/folly/Expected.h) (C++14).
+
+## Notes and references
+
+[1] Vicente J. Botet Escriba. [p0323 - A proposal to add a utility class to represent expected object (latest)](http://wg21.link/p0323) (HTML). ([r12](http://wg21.link/p0323r12), [r11](http://wg21.link/p0323r11), [r10](http://wg21.link/p0323r10), [r9](http://wg21.link/p0323r9), [r8](http://wg21.link/p0323r8), [r7](http://wg21.link/p0323r7), [r6](http://wg21.link/p0323r6), [r5](http://wg21.link/p0323r5), [r4](http://wg21.link/p0323r4), [r3](http://wg21.link/p0323r3), [r2](http://wg21.link/p0323r2), [r1](http://wg21.link/n4109), [r0](http://wg21.link/n4015), [draft](https://github.com/viboes/std-make/blob/master/doc/proposal/expected/DXXXXR0_expected.pdf)).
+
+[2] Vicente J. Botet Escriba. [JASEL: Just a simple experimental library for C++](https://github.com/viboes/std-make). Reference implementation of [expected](https://github.com/viboes/std-make/tree/master/include/experimental/fundamental/v3/expected).
+
+[3] Vicente J. Botet Escriba. [Expected - An exception-friendly Error Monad](https://www.youtube.com/watch?v=Zdlt1rgYdMQ). C++Now 2014. 24 September 2014.
+
+[4] Pierre Talbot. [Boost.Expected. Unofficial Boost candidate](http://www.google-melange.com/gsoc/proposal/review/google/gsoc2013/trademark/25002). 5 May 2013. [GitHub](https://github.com/TrademarkPewPew/Boost.Expected), [GSoC 2013 Proposal](http://www.google-melange.com/gsoc/proposal/review/google/gsoc2013/trademark/25002), [boost@lists.boost.org](http://permalink.gmane.org/gmane.comp.lib.boost.devel/240056 ).
+
+[5] Fernando Cacciola and Andrzej Krzemieński. [A proposal to add a utility class to represent optional objects (Revision 4)](http://isocpp.org/files/papers/N3672.html). ISO/IEC JTC1 SC22 WG21 N3672 2013-04-19.
+
+[6] Andrzej Krzemieński, [Optional library implementation in C++11](https://github.com/akrzemi1/Optional/).
+
+[7] Anto Nonco. [Extending expected<T> to deal with references](http://anto-nonco.blogspot.nl/2013/03/extending-expected-to-deal-with.html). 27 May 2013.
+
+[8] Andrei Alexandrescu. Systematic Error Handling in C++. Prepared for The C++and Beyond Seminar 2012. [Video](http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C). [Slides](http://sdrv.ms/RXjNPR).
+
+[9] Andrei Alexandrescu. [Choose your Poison: Exceptions or Error Codes? (PDF)](http://accu.org/content/conf2007/Alexandrescu-Choose_Your_Poison.pdf). ACCU Conference 2007.
+
+[10] Andrei Alexandrescu. [The Power of None (PPT)](http://nwcpp.org/static/talks/2006/The_Power_of_None.ppt). Northwest C++ Users' Group. [May 17th, 2006](http://nwcpp.org/may-2006.html).
+
+[11] Jon Jagger. [A Return Type That Doesn't Like Being Ignored](http://accu.org/var/uploads/journals/overload53-FINAL.pdf#page=18). Overload issue 53, February 2003.
+
+[12] Andrei Alexandrescu. [Error Handling in C++: Are we inching towards a total solution?](http://accu.org/index.php/conferences/2002/speakers2002). ACCU Conference 2002.
+
+[13] Ken Hagan et al. [Exploding return codes](https://groups.google.com/d/msg/comp.lang.c++.moderated/BkZqPfoq3ys/H_PMR8Sat4oJ). comp.lang.c++.moderated. 11 February 2000.
+
+[14] [std::pair](http://en.cppreference.com/w/cpp/utility/pair). cppreference.com
+
+[15] Niall Douglas. [Outcome](https://ned14.github.io/outcome/). Very lightweight outcome&lt;T> and result&lt;T> (non-Boost edition).
+
+[16] Niall Douglas. [p0762 - Concerns about expected&lt;T, E> from the Boost.Outcome peer review](http://wg21.link/p0762). 15 October 2017.
+
+[17] Jeff Garland. [p2505 - Monadic Functions for `std::expected`](http://wg21.link/p2505) (HTML). ([r0](http://wg21.link/p2505r0), [r1](http://wg21.link/p2505r1), [r2](http://wg21.link/p2505r2), [r3](http://wg21.link/p2505r3), [r4](http://wg21.link/p2505r4), [r5](http://wg21.link/p2505r5)).
+
+## Appendix
+
+### A.1 Compile-time information
+
+The version of *expected lite* is available via tag `[.version]`. The following tags are available for information on the compiler and on the C++ standard library used: `[.compiler]`, `[.stdc++]`, `[.stdlanguage]` and `[.stdlibrary]`.
+
+### A.2 Expected lite test specification
+
+<details>
+<summary>click to expand</summary>
+<p>
+
+```Text
+unexpected_type: Disallows default construction
+unexpected_type: Allows to copy-construct from unexpected_type, default
+unexpected_type: Allows to move-construct from unexpected_type, default
+unexpected_type: Allows to in-place-construct
+unexpected_type: Allows to in-place-construct from initializer_list
+unexpected_type: Allows to copy-construct from error_type
+unexpected_type: Allows to move-construct from error_type
+unexpected_type: Allows to copy-construct from unexpected_type, explicit converting
+unexpected_type: Allows to copy-construct from unexpected_type, non-explicit converting
+unexpected_type: Allows to move-construct from unexpected_type, explicit converting
+unexpected_type: Allows to move-construct from unexpected_type, non-explicit converting
+unexpected_type: Allows to copy-assign from unexpected_type, default
+unexpected_type: Allows to move-assign from unexpected_type, default
+unexpected_type: Allows to copy-assign from unexpected_type, converting
+unexpected_type: Allows to move-assign from unexpected, converting
+unexpected_type: Allows to observe its value via a l-value reference
+unexpected_type: Allows to observe its value via a r-value reference
+unexpected_type: Allows to modify its value via a l-value reference
+unexpected_type: Allows to be swapped
+unexpected_type<std::exception_ptr>: Disallows default construction
+unexpected_type<std::exception_ptr>: Allows to copy-construct from error_type
+unexpected_type<std::exception_ptr>: Allows to move-construct from error_type
+unexpected_type<std::exception_ptr>: Allows to copy-construct from an exception
+unexpected_type<std::exception_ptr>: Allows to observe its value
+unexpected_type<std::exception_ptr>: Allows to modify its value
+unexpected_type: Provides relational operators
+unexpected_type: Provides relational operators, std::exception_ptr specialization
+make_unexpected(): Allows to create an unexpected_type<E> from an E
+unexpected: C++17 and later provide unexpected_type as unexpected
+bad_expected_access: Disallows default construction
+bad_expected_access: Allows construction from error_type
+bad_expected_access: Allows to observe its error
+bad_expected_access: Allows to change its error
+bad_expected_access: Provides non-empty what()
+expected: Allows to default construct
+expected: Allows to default construct from noncopyable, noncopyable value type
+expected: Allows to default construct from noncopyable, noncopyable error type
+expected: Allows to copy-construct from expected: value
+expected: Allows to copy-construct from expected: error
+expected: Allows to move-construct from expected: value
+expected: Allows to move-construct from expected: error
+expected: Allows to copy-construct from expected; value, explicit converting
+expected: Allows to copy-construct from expected; error, explicit converting
+expected: Allows to copy-construct from expected; value, non-explicit converting
+expected: Allows to copy-construct from expected; error, non-explicit converting
+expected: Allows to move-construct from expected; value, explicit converting
+expected: Allows to move-construct from expected; error, explicit converting
+expected: Allows to move-construct from expected; value, non-explicit converting
+expected: Allows to move-construct from expected; error, non-explicit converting
+expected: Allows to forward-construct from value, explicit converting
+expected: Allows to forward-construct from value, non-explicit converting
+expected: Allows to in-place-construct value
+expected: Allows to in-place-construct value from initializer_list
+expected: Allows to copy-construct from unexpected, explicit converting
+expected: Allows to copy-construct from unexpected, non-explicit converting
+expected: Allows to move-construct from unexpected, explicit converting
+expected: Allows to move-construct from unexpected, non-explicit converting
+expected: Allows to in-place-construct error
+expected: Allows to in-place-construct error from initializer_list
+expected: Allows to copy-assign from expected, value
+expected: Allows to copy-assign from expected, error
+expected: Allows to move-assign from expected, value
+expected: Allows to move-assign from expected, error
+expected: Allows to forward-assign from value
+expected: Allows to copy-assign from unexpected
+expected: Allows to move-assign from unexpected
+expected: Allows to move-assign from move-only unexpected
+expected: Allows to emplace value
+expected: Allows to emplace value from initializer_list
+expected: Allows to be swapped
+expected: Allows to observe its value via a pointer
+expected: Allows to observe its value via a pointer to constant
+expected: Allows to modify its value via a pointer
+expected: Allows to observe its value via a l-value reference
+expected: Allows to observe its value via a r-value reference
+expected: Allows to modify its value via a l-value reference
+expected: Allows to modify its value via a r-value reference
+expected: Allows to observe if it contains a value (or error)
+expected: Allows to observe its value
+expected: Allows to modify its value
+expected: Allows to move its value
+expected: Allows to observe its error
+expected: Allows to modify its error
+expected: Allows to move its error
+expected: Allows to observe its error as unexpected
+expected: Allows to query if it contains an exception of a specific base type
+expected: Allows to observe its value if available, or obtain a specified value otherwise
+expected: Allows to move its value if available, or obtain a specified value otherwise
+expected: Throws bad_expected_access on value access when disengaged
+expected: Allows to observe its unexpected value, or fallback to the specified value with error_or [monadic p2505r4]
+expected: Allows to map value with and_then [monadic p2505r3]
+expected: Allows to map unexpected with or_else [monadic p2505r3]
+expected: Allows to transform value [monadic p2505r3]
+expected: Allows to map errors with transform_error [monadic p2505r3]
+expected<void>: Allows to default-construct
+expected<void>: Allows to copy-construct from expected<void>: value
+expected<void>: Allows to copy-construct from expected<void>: error
+expected<void>: Allows to move-construct from expected<void>: value
+expected<void>: Allows to move-construct from expected<void>: error
+expected<void>: Allows to in-place-construct
+expected<void>: Allows to copy-construct from unexpected, explicit converting
+expected<void>: Allows to copy-construct from unexpected, non-explicit converting
+expected<void>: Allows to move-construct from unexpected, explicit converting
+expected<void>: Allows to move-construct from unexpected, non-explicit converting
+expected<void>: Allows to in-place-construct unexpected_type
+expected<void>: Allows to in-place-construct error from initializer_list
+expected<void>: Allows to copy-assign from expected, value
+expected<void>: Allows to copy-assign from expected, error
+expected<void>: Allows to move-assign from expected, value
+expected<void>: Allows to move-assign from expected, error
+expected<void>: Allows to emplace value
+expected<void>: Allows to be swapped
+expected<void>: Allows to observe if it contains a value (or error)
+expected<void>: Allows to observe its value
+expected<void>: Allows to observe its error
+expected<void>: Allows to modify its error
+expected<void>: Allows to move its error
+expected<void>: Allows to observe its error as unexpected
+expected<void>: Allows to query if it contains an exception of a specific base type
+expected<void>: Throws bad_expected_access on value access when disengaged
+expected<void>: Allows to observe unexpected value, or fallback to a default value with error_or [monadic p2505r4]
+expected<void>: Allows to call argless functions with and_then [monadic p2505r3]
+expected<void>: Allows to map to expected or unexpected with or_else [monadic p2505r3]
+expected<void>: Allows to assign a new expected value using transform [monadic p2505r3]
+expected<void>: Allows to map unexpected error value via transform_error [monadic p2505r3]
+operators: Provides expected relational operators
+operators: Provides expected relational operators (void)
+swap: Allows expected to be swapped
+std::hash: Allows to compute hash value for expected
+tweak header: reads tweak header if supported [tweak]
+```
+
+</p>
+</details>
diff --git a/contrib/restricted/expected-lite/include/nonstd/expected.hpp b/contrib/restricted/expected-lite/include/nonstd/expected.hpp
new file mode 100644
index 0000000000..588ba1a22e
--- /dev/null
+++ b/contrib/restricted/expected-lite/include/nonstd/expected.hpp
@@ -0,0 +1,3555 @@
+// This version targets C++11 and later.
+//
+// Copyright (C) 2016-2020 Martin Moene.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// expected lite is based on:
+// A proposal to add a utility class to represent expected monad
+// by Vicente J. Botet Escriba and Pierre Talbot. http:://wg21.link/p0323
+
+#ifndef NONSTD_EXPECTED_LITE_HPP
+#define NONSTD_EXPECTED_LITE_HPP
+
+#define expected_lite_MAJOR 0
+#define expected_lite_MINOR 8
+#define expected_lite_PATCH 0
+
+#define expected_lite_VERSION expected_STRINGIFY(expected_lite_MAJOR) "." expected_STRINGIFY(expected_lite_MINOR) "." expected_STRINGIFY(expected_lite_PATCH)
+
+#define expected_STRINGIFY( x ) expected_STRINGIFY_( x )
+#define expected_STRINGIFY_( x ) #x
+
+// expected-lite configuration:
+
+#define nsel_EXPECTED_DEFAULT 0
+#define nsel_EXPECTED_NONSTD 1
+#define nsel_EXPECTED_STD 2
+
+// tweak header support:
+
+#ifdef __has_include
+# if __has_include(<nonstd/expected.tweak.hpp>)
+# error #include <nonstd/expected.tweak.hpp>
+# endif
+#define expected_HAVE_TWEAK_HEADER 1
+#else
+#define expected_HAVE_TWEAK_HEADER 0
+//# pragma message("expected.hpp: Note: Tweak header not supported.")
+#endif
+
+// expected selection and configuration:
+
+#if !defined( nsel_CONFIG_SELECT_EXPECTED )
+# define nsel_CONFIG_SELECT_EXPECTED ( nsel_HAVE_STD_EXPECTED ? nsel_EXPECTED_STD : nsel_EXPECTED_NONSTD )
+#endif
+
+// Proposal revisions:
+//
+// DXXXXR0: --
+// N4015 : -2 (2014-05-26)
+// N4109 : -1 (2014-06-29)
+// P0323R0: 0 (2016-05-28)
+// P0323R1: 1 (2016-10-12)
+// -------:
+// P0323R2: 2 (2017-06-15)
+// P0323R3: 3 (2017-10-15)
+// P0323R4: 4 (2017-11-26)
+// P0323R5: 5 (2018-02-08)
+// P0323R6: 6 (2018-04-02)
+// P0323R7: 7 (2018-06-22) *
+//
+// expected-lite uses 2 and higher
+
+#ifndef nsel_P0323R
+# define nsel_P0323R 7
+#endif
+
+// Monadic operations proposal revisions:
+//
+// P2505R0: 0 (2021-12-12)
+// P2505R1: 1 (2022-02-10)
+// P2505R2: 2 (2022-04-15)
+// P2505R3: 3 (2022-06-05)
+// P2505R4: 4 (2022-06-15)
+// P2505R5: 5 (2022-09-20) *
+//
+// expected-lite uses 5
+
+#ifndef nsel_P2505R
+# define nsel_P2505R 5
+#endif
+
+// Control presence of C++ exception handling (try and auto discover):
+
+#ifndef nsel_CONFIG_NO_EXCEPTIONS
+# if defined(_MSC_VER)
+# include <cstddef> // for _HAS_EXCEPTIONS
+# endif
+# if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
+# define nsel_CONFIG_NO_EXCEPTIONS 0
+# else
+# define nsel_CONFIG_NO_EXCEPTIONS 1
+# endif
+#endif
+
+// at default use SEH with MSVC for no C++ exceptions
+
+#ifndef nsel_CONFIG_NO_EXCEPTIONS_SEH
+# define nsel_CONFIG_NO_EXCEPTIONS_SEH ( nsel_CONFIG_NO_EXCEPTIONS && _MSC_VER )
+#endif
+
+// C++ language version detection (C++23 is speculative):
+// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
+
+#ifndef nsel_CPLUSPLUS
+# if defined(_MSVC_LANG ) && !defined(__clang__)
+# define nsel_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
+# else
+# define nsel_CPLUSPLUS __cplusplus
+# endif
+#endif
+
+#define nsel_CPP98_OR_GREATER ( nsel_CPLUSPLUS >= 199711L )
+#define nsel_CPP11_OR_GREATER ( nsel_CPLUSPLUS >= 201103L )
+#define nsel_CPP14_OR_GREATER ( nsel_CPLUSPLUS >= 201402L )
+#define nsel_CPP17_OR_GREATER ( nsel_CPLUSPLUS >= 201703L )
+#define nsel_CPP20_OR_GREATER ( nsel_CPLUSPLUS >= 202002L )
+#define nsel_CPP23_OR_GREATER ( nsel_CPLUSPLUS >= 202300L )
+
+// Use C++23 std::expected if available and requested:
+
+#if nsel_CPP23_OR_GREATER && defined(__has_include )
+# if __has_include( <expected> )
+# define nsel_HAVE_STD_EXPECTED 1
+# else
+# define nsel_HAVE_STD_EXPECTED 0
+# endif
+#else
+# define nsel_HAVE_STD_EXPECTED 0
+#endif
+
+#define nsel_USES_STD_EXPECTED ( (nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_STD) || ((nsel_CONFIG_SELECT_EXPECTED == nsel_EXPECTED_DEFAULT) && nsel_HAVE_STD_EXPECTED) )
+
+//
+// in_place: code duplicated in any-lite, expected-lite, expected-lite, value-ptr-lite, variant-lite:
+//
+
+#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
+#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
+
+// C++17 std::in_place in <utility>:
+
+#if nsel_CPP17_OR_GREATER
+
+#include <utility>
+
+namespace nonstd {
+
+using std::in_place;
+using std::in_place_type;
+using std::in_place_index;
+using std::in_place_t;
+using std::in_place_type_t;
+using std::in_place_index_t;
+
+#define nonstd_lite_in_place_t( T) std::in_place_t
+#define nonstd_lite_in_place_type_t( T) std::in_place_type_t<T>
+#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
+
+#define nonstd_lite_in_place( T) std::in_place_t{}
+#define nonstd_lite_in_place_type( T) std::in_place_type_t<T>{}
+#define nonstd_lite_in_place_index(K) std::in_place_index_t<K>{}
+
+} // namespace nonstd
+
+#else // nsel_CPP17_OR_GREATER
+
+#include <cstddef>
+
+namespace nonstd {
+namespace detail {
+
+template< class T >
+struct in_place_type_tag {};
+
+template< std::size_t K >
+struct in_place_index_tag {};
+
+} // namespace detail
+
+struct in_place_t {};
+
+template< class T >
+inline in_place_t in_place( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
+{
+ return in_place_t();
+}
+
+template< std::size_t K >
+inline in_place_t in_place( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
+{
+ return in_place_t();
+}
+
+template< class T >
+inline in_place_t in_place_type( detail::in_place_type_tag<T> = detail::in_place_type_tag<T>() )
+{
+ return in_place_t();
+}
+
+template< std::size_t K >
+inline in_place_t in_place_index( detail::in_place_index_tag<K> = detail::in_place_index_tag<K>() )
+{
+ return in_place_t();
+}
+
+// mimic templated typedef:
+
+#define nonstd_lite_in_place_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
+#define nonstd_lite_in_place_type_t( T) nonstd::in_place_t(&)( nonstd::detail::in_place_type_tag<T> )
+#define nonstd_lite_in_place_index_t(K) nonstd::in_place_t(&)( nonstd::detail::in_place_index_tag<K> )
+
+#define nonstd_lite_in_place( T) nonstd::in_place_type<T>
+#define nonstd_lite_in_place_type( T) nonstd::in_place_type<T>
+#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
+
+} // namespace nonstd
+
+#endif // nsel_CPP17_OR_GREATER
+#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
+
+//
+// Using std::expected:
+//
+
+#if nsel_USES_STD_EXPECTED
+
+#error #include <expected>
+
+namespace nonstd {
+
+ using std::expected;
+ using std::unexpected;
+ using std::bad_expected_access;
+ using std::unexpect_t;
+ using std::unexpect;
+
+ //[[deprecated("replace unexpected_type with unexpected")]]
+
+ template< typename E >
+ using unexpected_type = unexpected<E>;
+
+ // Unconditionally provide make_unexpected():
+
+ template< typename E>
+ constexpr auto make_unexpected( E && value ) -> unexpected< typename std::decay<E>::type >
+ {
+ return unexpected< typename std::decay<E>::type >( std::forward<E>(value) );
+ }
+} // namespace nonstd
+
+#else // nsel_USES_STD_EXPECTED
+
+#include <cassert>
+#include <exception>
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <new>
+#include <system_error>
+#include <type_traits>
+#include <utility>
+
+// additional includes:
+
+#if nsel_CONFIG_NO_EXCEPTIONS
+# if nsel_CONFIG_NO_EXCEPTIONS_SEH
+# include <windows.h> // for ExceptionCodes
+# else
+// already included: <cassert>
+# endif
+#else
+# include <stdexcept>
+#endif
+
+// C++ feature usage:
+
+#if nsel_CPP11_OR_GREATER
+# define nsel_constexpr constexpr
+#else
+# define nsel_constexpr /*constexpr*/
+#endif
+
+#if nsel_CPP14_OR_GREATER
+# define nsel_constexpr14 constexpr
+#else
+# define nsel_constexpr14 /*constexpr*/
+#endif
+
+#if nsel_CPP17_OR_GREATER
+# define nsel_inline17 inline
+#else
+# define nsel_inline17 /*inline*/
+#endif
+
+// Compiler versions:
+//
+// MSVC++ 6.0 _MSC_VER == 1200 nsel_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
+// MSVC++ 7.0 _MSC_VER == 1300 nsel_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
+// MSVC++ 7.1 _MSC_VER == 1310 nsel_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
+// MSVC++ 8.0 _MSC_VER == 1400 nsel_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
+// MSVC++ 9.0 _MSC_VER == 1500 nsel_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
+// MSVC++ 10.0 _MSC_VER == 1600 nsel_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
+// MSVC++ 11.0 _MSC_VER == 1700 nsel_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
+// MSVC++ 12.0 _MSC_VER == 1800 nsel_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
+// MSVC++ 14.0 _MSC_VER == 1900 nsel_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
+// MSVC++ 14.1 _MSC_VER >= 1910 nsel_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
+// MSVC++ 14.2 _MSC_VER >= 1920 nsel_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
+
+#if defined(_MSC_VER) && !defined(__clang__)
+# define nsel_COMPILER_MSVC_VER (_MSC_VER )
+# define nsel_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900)) )
+#else
+# define nsel_COMPILER_MSVC_VER 0
+# define nsel_COMPILER_MSVC_VERSION 0
+#endif
+
+#define nsel_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
+
+#if defined(__clang__)
+# define nsel_COMPILER_CLANG_VERSION nsel_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#else
+# define nsel_COMPILER_CLANG_VERSION 0
+#endif
+
+#if defined(__GNUC__) && !defined(__clang__)
+# define nsel_COMPILER_GNUC_VERSION nsel_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#else
+# define nsel_COMPILER_GNUC_VERSION 0
+#endif
+
+// half-open range [lo..hi):
+//#define nsel_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
+
+// Method enabling
+
+#define nsel_REQUIRES_0(...) \
+ template< bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0 >
+
+#define nsel_REQUIRES_T(...) \
+ , typename std::enable_if< (__VA_ARGS__), int >::type = 0
+
+#define nsel_REQUIRES_R(R, ...) \
+ typename std::enable_if< (__VA_ARGS__), R>::type
+
+#define nsel_REQUIRES_A(...) \
+ , typename std::enable_if< (__VA_ARGS__), void*>::type = nullptr
+
+// Clang, GNUC, MSVC warning suppression macros:
+
+#ifdef __clang__
+# pragma clang diagnostic push
+#elif defined __GNUC__
+# pragma GCC diagnostic push
+#endif // __clang__
+
+#if nsel_COMPILER_MSVC_VERSION >= 140
+# define nsel_DISABLE_MSVC_WARNINGS(codes) __pragma( warning(push) ) __pragma( warning(disable: codes) )
+#else
+# define nsel_DISABLE_MSVC_WARNINGS(codes)
+#endif
+
+#ifdef __clang__
+# define nsel_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
+# define nsel_RESTORE_MSVC_WARNINGS()
+#elif defined __GNUC__
+# define nsel_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
+# define nsel_RESTORE_MSVC_WARNINGS()
+#elif nsel_COMPILER_MSVC_VERSION >= 140
+# define nsel_RESTORE_WARNINGS() __pragma( warning( pop ) )
+# define nsel_RESTORE_MSVC_WARNINGS() nsel_RESTORE_WARNINGS()
+#else
+# define nsel_RESTORE_WARNINGS()
+# define nsel_RESTORE_MSVC_WARNINGS()
+#endif
+
+// Suppress the following MSVC (GSL) warnings:
+// - C26409: Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11)
+
+nsel_DISABLE_MSVC_WARNINGS( 26409 )
+
+// Presence of language and library features:
+
+#ifdef _HAS_CPP0X
+# define nsel_HAS_CPP0X _HAS_CPP0X
+#else
+# define nsel_HAS_CPP0X 0
+#endif
+
+// Presence of language and library features:
+
+#define nsel_CPP17_000 (nsel_CPP17_OR_GREATER)
+
+// Presence of C++17 language features:
+
+#define nsel_HAVE_DEPRECATED nsel_CPP17_000
+
+// C++ feature usage:
+
+#if nsel_HAVE_DEPRECATED
+# define nsel_deprecated(msg) [[deprecated(msg)]]
+#else
+# define nsel_deprecated(msg) /*[[deprecated]]*/
+#endif
+
+//
+// expected:
+//
+
+namespace nonstd { namespace expected_lite {
+
+// type traits C++17:
+
+namespace std17 {
+
+#if nsel_CPP17_OR_GREATER
+
+using std::conjunction;
+using std::is_swappable;
+using std::is_nothrow_swappable;
+
+#else // nsel_CPP17_OR_GREATER
+
+namespace detail {
+
+using std::swap;
+
+struct is_swappable
+{
+ template< typename T, typename = decltype( swap( std::declval<T&>(), std::declval<T&>() ) ) >
+ static std::true_type test( int /* unused */);
+
+ template< typename >
+ static std::false_type test(...);
+};
+
+struct is_nothrow_swappable
+{
+ // wrap noexcept(expr) in separate function as work-around for VC140 (VS2015):
+
+ template< typename T >
+ static constexpr bool satisfies()
+ {
+ return noexcept( swap( std::declval<T&>(), std::declval<T&>() ) );
+ }
+
+ template< typename T >
+ static auto test( int ) -> std::integral_constant<bool, satisfies<T>()>{}
+
+ template< typename >
+ static auto test(...) -> std::false_type;
+};
+} // namespace detail
+
+// is [nothrow] swappable:
+
+template< typename T >
+struct is_swappable : decltype( detail::is_swappable::test<T>(0) ){};
+
+template< typename T >
+struct is_nothrow_swappable : decltype( detail::is_nothrow_swappable::test<T>(0) ){};
+
+// conjunction:
+
+template< typename... > struct conjunction : std::true_type{};
+template< typename B1 > struct conjunction<B1> : B1{};
+
+template< typename B1, typename... Bn >
+struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type{};
+
+#endif // nsel_CPP17_OR_GREATER
+
+} // namespace std17
+
+// type traits C++20:
+
+namespace std20 {
+
+#if defined(__cpp_lib_remove_cvref)
+
+using std::remove_cvref;
+
+#else
+
+template< typename T >
+struct remove_cvref
+{
+ typedef typename std::remove_cv< typename std::remove_reference<T>::type >::type type;
+};
+
+#endif
+
+} // namespace std20
+
+// forward declaration:
+
+template< typename T, typename E >
+class expected;
+
+namespace detail {
+
+#if nsel_P2505R >= 3
+template< typename T >
+struct is_expected : std::false_type {};
+
+template< typename T, typename E >
+struct is_expected< expected< T, E > > : std::true_type {};
+#endif // nsel_P2505R >= 3
+
+/// discriminated union to hold value or 'error'.
+
+template< typename T, typename E >
+class storage_t_noncopy_nonmove_impl
+{
+ template< typename, typename > friend class nonstd::expected_lite::expected;
+
+public:
+ using value_type = T;
+ using error_type = E;
+
+ // no-op construction
+ storage_t_noncopy_nonmove_impl() {}
+ ~storage_t_noncopy_nonmove_impl() {}
+
+ explicit storage_t_noncopy_nonmove_impl( bool has_value )
+ : m_has_value( has_value )
+ {}
+
+ void construct_value()
+ {
+ new( &m_value ) value_type();
+ }
+
+ // void construct_value( value_type const & e )
+ // {
+ // new( &m_value ) value_type( e );
+ // }
+
+ // void construct_value( value_type && e )
+ // {
+ // new( &m_value ) value_type( std::move( e ) );
+ // }
+
+ template< class... Args >
+ void emplace_value( Args&&... args )
+ {
+ new( &m_value ) value_type( std::forward<Args>(args)...);
+ }
+
+ template< class U, class... Args >
+ void emplace_value( std::initializer_list<U> il, Args&&... args )
+ {
+ new( &m_value ) value_type( il, std::forward<Args>(args)... );
+ }
+
+ void destruct_value()
+ {
+ m_value.~value_type();
+ }
+
+ // void construct_error( error_type const & e )
+ // {
+ // // new( &m_error ) error_type( e );
+ // }
+
+ // void construct_error( error_type && e )
+ // {
+ // // new( &m_error ) error_type( std::move( e ) );
+ // }
+
+ template< class... Args >
+ void emplace_error( Args&&... args )
+ {
+ new( &m_error ) error_type( std::forward<Args>(args)...);
+ }
+
+ template< class U, class... Args >
+ void emplace_error( std::initializer_list<U> il, Args&&... args )
+ {
+ new( &m_error ) error_type( il, std::forward<Args>(args)... );
+ }
+
+ void destruct_error()
+ {
+ m_error.~error_type();
+ }
+
+ constexpr value_type const & value() const &
+ {
+ return m_value;
+ }
+
+ value_type & value() &
+ {
+ return m_value;
+ }
+
+ constexpr value_type const && value() const &&
+ {
+ return std::move( m_value );
+ }
+
+ nsel_constexpr14 value_type && value() &&
+ {
+ return std::move( m_value );
+ }
+
+ value_type const * value_ptr() const
+ {
+ return &m_value;
+ }
+
+ value_type * value_ptr()
+ {
+ return &m_value;
+ }
+
+ error_type const & error() const &
+ {
+ return m_error;
+ }
+
+ error_type & error() &
+ {
+ return m_error;
+ }
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( m_error );
+ }
+
+ nsel_constexpr14 error_type && error() &&
+ {
+ return std::move( m_error );
+ }
+
+ bool has_value() const
+ {
+ return m_has_value;
+ }
+
+ void set_has_value( bool v )
+ {
+ m_has_value = v;
+ }
+
+private:
+ union
+ {
+ value_type m_value;
+ error_type m_error;
+ };
+
+ bool m_has_value = false;
+};
+
+template< typename T, typename E >
+class storage_t_impl
+{
+ template< typename, typename > friend class nonstd::expected_lite::expected;
+
+public:
+ using value_type = T;
+ using error_type = E;
+
+ // no-op construction
+ storage_t_impl() {}
+ ~storage_t_impl() {}
+
+ explicit storage_t_impl( bool has_value )
+ : m_has_value( has_value )
+ {}
+
+ void construct_value()
+ {
+ new( &m_value ) value_type();
+ }
+
+ void construct_value( value_type const & e )
+ {
+ new( &m_value ) value_type( e );
+ }
+
+ void construct_value( value_type && e )
+ {
+ new( &m_value ) value_type( std::move( e ) );
+ }
+
+ template< class... Args >
+ void emplace_value( Args&&... args )
+ {
+ new( &m_value ) value_type( std::forward<Args>(args)...);
+ }
+
+ template< class U, class... Args >
+ void emplace_value( std::initializer_list<U> il, Args&&... args )
+ {
+ new( &m_value ) value_type( il, std::forward<Args>(args)... );
+ }
+
+ void destruct_value()
+ {
+ m_value.~value_type();
+ }
+
+ void construct_error( error_type const & e )
+ {
+ new( &m_error ) error_type( e );
+ }
+
+ void construct_error( error_type && e )
+ {
+ new( &m_error ) error_type( std::move( e ) );
+ }
+
+ template< class... Args >
+ void emplace_error( Args&&... args )
+ {
+ new( &m_error ) error_type( std::forward<Args>(args)...);
+ }
+
+ template< class U, class... Args >
+ void emplace_error( std::initializer_list<U> il, Args&&... args )
+ {
+ new( &m_error ) error_type( il, std::forward<Args>(args)... );
+ }
+
+ void destruct_error()
+ {
+ m_error.~error_type();
+ }
+
+ constexpr value_type const & value() const &
+ {
+ return m_value;
+ }
+
+ value_type & value() &
+ {
+ return m_value;
+ }
+
+ constexpr value_type const && value() const &&
+ {
+ return std::move( m_value );
+ }
+
+ nsel_constexpr14 value_type && value() &&
+ {
+ return std::move( m_value );
+ }
+
+ value_type const * value_ptr() const
+ {
+ return &m_value;
+ }
+
+ value_type * value_ptr()
+ {
+ return &m_value;
+ }
+
+ error_type const & error() const &
+ {
+ return m_error;
+ }
+
+ error_type & error() &
+ {
+ return m_error;
+ }
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( m_error );
+ }
+
+ nsel_constexpr14 error_type && error() &&
+ {
+ return std::move( m_error );
+ }
+
+ bool has_value() const
+ {
+ return m_has_value;
+ }
+
+ void set_has_value( bool v )
+ {
+ m_has_value = v;
+ }
+
+private:
+ union
+ {
+ value_type m_value;
+ error_type m_error;
+ };
+
+ bool m_has_value = false;
+};
+
+/// discriminated union to hold only 'error'.
+
+template< typename E >
+struct storage_t_impl<void, E>
+{
+ template< typename, typename > friend class nonstd::expected_lite::expected;
+
+public:
+ using value_type = void;
+ using error_type = E;
+
+ // no-op construction
+ storage_t_impl() {}
+ ~storage_t_impl() {}
+
+ explicit storage_t_impl( bool has_value )
+ : m_has_value( has_value )
+ {}
+
+ void construct_error( error_type const & e )
+ {
+ new( &m_error ) error_type( e );
+ }
+
+ void construct_error( error_type && e )
+ {
+ new( &m_error ) error_type( std::move( e ) );
+ }
+
+ template< class... Args >
+ void emplace_error( Args&&... args )
+ {
+ new( &m_error ) error_type( std::forward<Args>(args)...);
+ }
+
+ template< class U, class... Args >
+ void emplace_error( std::initializer_list<U> il, Args&&... args )
+ {
+ new( &m_error ) error_type( il, std::forward<Args>(args)... );
+ }
+
+ void destruct_error()
+ {
+ m_error.~error_type();
+ }
+
+ error_type const & error() const &
+ {
+ return m_error;
+ }
+
+ error_type & error() &
+ {
+ return m_error;
+ }
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( m_error );
+ }
+
+ nsel_constexpr14 error_type && error() &&
+ {
+ return std::move( m_error );
+ }
+
+ bool has_value() const
+ {
+ return m_has_value;
+ }
+
+ void set_has_value( bool v )
+ {
+ m_has_value = v;
+ }
+
+private:
+ union
+ {
+ char m_dummy;
+ error_type m_error;
+ };
+
+ bool m_has_value = false;
+};
+
+template< typename T, typename E, bool isConstructable, bool isMoveable >
+class storage_t
+{
+public:
+};
+
+template< typename T, typename E >
+class storage_t<T, E, false, false> : public storage_t_noncopy_nonmove_impl<T, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_noncopy_nonmove_impl<T, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other ) = delete;
+ storage_t( storage_t && other ) = delete;
+
+};
+
+template< typename T, typename E >
+class storage_t<T, E, true, true> : public storage_t_impl<T, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<T, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other )
+ : storage_t_impl<T, E>( other.has_value() )
+ {
+ if ( this->has_value() ) this->construct_value( other.value() );
+ else this->construct_error( other.error() );
+ }
+
+ storage_t(storage_t && other )
+ : storage_t_impl<T, E>( other.has_value() )
+ {
+ if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
+ else this->construct_error( std::move( other.error() ) );
+ }
+};
+
+template< typename E >
+class storage_t<void, E, true, true> : public storage_t_impl<void, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<void, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other )
+ : storage_t_impl<void, E>( other.has_value() )
+ {
+ if ( this->has_value() ) ;
+ else this->construct_error( other.error() );
+ }
+
+ storage_t(storage_t && other )
+ : storage_t_impl<void, E>( other.has_value() )
+ {
+ if ( this->has_value() ) ;
+ else this->construct_error( std::move( other.error() ) );
+ }
+};
+
+template< typename T, typename E >
+class storage_t<T, E, true, false> : public storage_t_impl<T, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<T, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other )
+ : storage_t_impl<T, E>(other.has_value())
+ {
+ if ( this->has_value() ) this->construct_value( other.value() );
+ else this->construct_error( other.error() );
+ }
+
+ storage_t( storage_t && other ) = delete;
+};
+
+template< typename E >
+class storage_t<void, E, true, false> : public storage_t_impl<void, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<void, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other )
+ : storage_t_impl<void, E>(other.has_value())
+ {
+ if ( this->has_value() ) ;
+ else this->construct_error( other.error() );
+ }
+
+ storage_t( storage_t && other ) = delete;
+};
+
+template< typename T, typename E >
+class storage_t<T, E, false, true> : public storage_t_impl<T, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<T, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other ) = delete;
+
+ storage_t( storage_t && other )
+ : storage_t_impl<T, E>( other.has_value() )
+ {
+ if ( this->has_value() ) this->construct_value( std::move( other.value() ) );
+ else this->construct_error( std::move( other.error() ) );
+ }
+};
+
+template< typename E >
+class storage_t<void, E, false, true> : public storage_t_impl<void, E>
+{
+public:
+ storage_t() = default;
+ ~storage_t() = default;
+
+ explicit storage_t( bool has_value )
+ : storage_t_impl<void, E>( has_value )
+ {}
+
+ storage_t( storage_t const & other ) = delete;
+
+ storage_t( storage_t && other )
+ : storage_t_impl<void, E>( other.has_value() )
+ {
+ if ( this->has_value() ) ;
+ else this->construct_error( std::move( other.error() ) );
+ }
+};
+
+#if nsel_P2505R >= 3
+// C++11 invoke implementation
+template< typename >
+struct is_reference_wrapper : std::false_type {};
+template< typename T >
+struct is_reference_wrapper< std::reference_wrapper< T > > : std::true_type {};
+
+template< typename FnT, typename ClassT, typename ObjectT, typename... Args
+ nsel_REQUIRES_T(
+ std::is_function<FnT>::value
+ && ( std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value )
+ )
+>
+nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
+ noexcept( noexcept( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... ) ) )
+ -> decltype( (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )...) )
+{
+ return (std::forward< ObjectT >( obj ).*memfnptr)( std::forward< Args >( args )... );
+}
+
+template< typename FnT, typename ClassT, typename ObjectT, typename... Args
+ nsel_REQUIRES_T(
+ std::is_function<FnT>::value
+ && is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
+ )
+>
+nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
+ noexcept( noexcept( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) ) )
+ -> decltype( (obj.get().*memfnptr)( std::forward< Args >( args ) ... ) )
+{
+ return (obj.get().*memfnptr)( std::forward< Args >( args ) ... );
+}
+
+template< typename FnT, typename ClassT, typename ObjectT, typename... Args
+ nsel_REQUIRES_T(
+ std::is_function<FnT>::value
+ && !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
+ )
+>
+nsel_constexpr auto invoke_member_function_impl( FnT ClassT::* memfnptr, ObjectT && obj, Args && ... args )
+ noexcept( noexcept( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) ) )
+ -> decltype( ((*std::forward< ObjectT >( obj )).*memfnptr)( std::forward< Args >( args ) ... ) )
+{
+ return ((*std::forward<ObjectT>(obj)).*memfnptr)( std::forward< Args >( args ) ... );
+}
+
+template< typename MemberT, typename ClassT, typename ObjectT
+ nsel_REQUIRES_T(
+ std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ || std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ )
+>
+nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
+ noexcept( noexcept( std::forward< ObjectT >( obj ).*memobjptr ) )
+ -> decltype( std::forward< ObjectT >( obj ).*memobjptr )
+{
+ return std::forward< ObjectT >( obj ).*memobjptr;
+}
+
+template< typename MemberT, typename ClassT, typename ObjectT
+ nsel_REQUIRES_T(
+ is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
+ )
+>
+nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
+ noexcept( noexcept( obj.get().*memobjptr ) )
+ -> decltype( obj.get().*memobjptr )
+{
+ return obj.get().*memobjptr;
+}
+
+template< typename MemberT, typename ClassT, typename ObjectT
+ nsel_REQUIRES_T(
+ !std::is_same< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ && !std::is_base_of< ClassT, typename std20::remove_cvref< ObjectT >::type >::value
+ && !is_reference_wrapper< typename std20::remove_cvref< ObjectT >::type >::value
+ )
+>
+nsel_constexpr auto invoke_member_object_impl( MemberT ClassT::* memobjptr, ObjectT && obj )
+ noexcept( noexcept( (*std::forward< ObjectT >( obj )).*memobjptr ) )
+ -> decltype( (*std::forward< ObjectT >( obj )).*memobjptr )
+{
+ return (*std::forward< ObjectT >( obj )).*memobjptr;
+}
+
+template< typename F, typename... Args
+ nsel_REQUIRES_T(
+ std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value
+ )
+>
+nsel_constexpr auto invoke( F && f, Args && ... args )
+ noexcept( noexcept( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) )
+ -> decltype( invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) )
+{
+ return invoke_member_function_impl( std::forward< F >( f ), std::forward< Args >( args ) ... );
+}
+
+template< typename F, typename... Args
+ nsel_REQUIRES_T(
+ std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value
+ )
+>
+nsel_constexpr auto invoke( F && f, Args && ... args )
+ noexcept( noexcept( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) ) )
+ -> decltype( invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... ) )
+{
+ return invoke_member_object_impl( std::forward< F >( f ), std::forward< Args >( args ) ... );
+}
+
+template< typename F, typename... Args
+ nsel_REQUIRES_T(
+ !std::is_member_function_pointer< typename std20::remove_cvref< F >::type >::value
+ && !std::is_member_object_pointer< typename std20::remove_cvref< F >::type >::value
+ )
+>
+nsel_constexpr auto invoke( F && f, Args && ... args )
+ noexcept( noexcept( std::forward< F >( f )( std::forward< Args >( args ) ... ) ) )
+ -> decltype( std::forward< F >( f )( std::forward< Args >( args ) ... ) )
+{
+ return std::forward< F >( f )( std::forward< Args >( args ) ... );
+}
+
+template< typename F, typename ... Args >
+using invoke_result_nocvref_t = typename std20::remove_cvref< decltype( invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type;
+
+#if nsel_P2505R >= 5
+template< typename F, typename ... Args >
+using transform_invoke_result_t = typename std::remove_cv< decltype( invoke( std::declval< F >(), std::declval< Args >()... ) ) >::type;
+#else
+template< typename F, typename ... Args >
+using transform_invoke_result_t = invoke_result_nocvref_t
+#endif // nsel_P2505R >= 5
+
+template< typename T >
+struct valid_expected_value_type : std::integral_constant< bool, std::is_destructible< T >::value && !std::is_reference< T >::value && !std::is_array< T >::value > {};
+
+#endif // nsel_P2505R >= 3
+} // namespace detail
+
+/// x.x.5 Unexpected object type; unexpected_type; C++17 and later can also use aliased type unexpected.
+
+#if nsel_P0323R <= 2
+template< typename E = std::exception_ptr >
+class unexpected_type
+#else
+template< typename E >
+class unexpected_type
+#endif // nsel_P0323R
+{
+public:
+ using error_type = E;
+
+ // x.x.5.2.1 Constructors
+
+// unexpected_type() = delete;
+
+ constexpr unexpected_type( unexpected_type const & ) = default;
+ constexpr unexpected_type( unexpected_type && ) = default;
+
+ template< typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, Args&&...>::value
+ )
+ >
+ constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), Args &&... args )
+ : m_error( std::forward<Args>( args )...)
+ {}
+
+ template< typename U, typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
+ )
+ >
+ constexpr explicit unexpected_type( nonstd_lite_in_place_t(E), std::initializer_list<U> il, Args &&... args )
+ : m_error( il, std::forward<Args>( args )...)
+ {}
+
+ template< typename E2
+ nsel_REQUIRES_T(
+ std::is_constructible<E,E2>::value
+ && !std::is_same< typename std20::remove_cvref<E2>::type, nonstd_lite_in_place_t(E2) >::value
+ && !std::is_same< typename std20::remove_cvref<E2>::type, unexpected_type >::value
+ )
+ >
+ constexpr explicit unexpected_type( E2 && error )
+ : m_error( std::forward<E2>( error ) )
+ {}
+
+ template< typename E2
+ nsel_REQUIRES_T(
+ std::is_constructible< E, E2>::value
+ && !std::is_constructible<E, unexpected_type<E2> & >::value
+ && !std::is_constructible<E, unexpected_type<E2> >::value
+ && !std::is_constructible<E, unexpected_type<E2> const & >::value
+ && !std::is_constructible<E, unexpected_type<E2> const >::value
+ && !std::is_convertible< unexpected_type<E2> &, E>::value
+ && !std::is_convertible< unexpected_type<E2> , E>::value
+ && !std::is_convertible< unexpected_type<E2> const &, E>::value
+ && !std::is_convertible< unexpected_type<E2> const , E>::value
+ && !std::is_convertible< E2 const &, E>::value /*=> explicit */
+ )
+ >
+ constexpr explicit unexpected_type( unexpected_type<E2> const & error )
+ : m_error( E{ error.error() } )
+ {}
+
+ template< typename E2
+ nsel_REQUIRES_T(
+ std::is_constructible< E, E2>::value
+ && !std::is_constructible<E, unexpected_type<E2> & >::value
+ && !std::is_constructible<E, unexpected_type<E2> >::value
+ && !std::is_constructible<E, unexpected_type<E2> const & >::value
+ && !std::is_constructible<E, unexpected_type<E2> const >::value
+ && !std::is_convertible< unexpected_type<E2> &, E>::value
+ && !std::is_convertible< unexpected_type<E2> , E>::value
+ && !std::is_convertible< unexpected_type<E2> const &, E>::value
+ && !std::is_convertible< unexpected_type<E2> const , E>::value
+ && std::is_convertible< E2 const &, E>::value /*=> explicit */
+ )
+ >
+ constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> const & error )
+ : m_error( error.error() )
+ {}
+
+ template< typename E2
+ nsel_REQUIRES_T(
+ std::is_constructible< E, E2>::value
+ && !std::is_constructible<E, unexpected_type<E2> & >::value
+ && !std::is_constructible<E, unexpected_type<E2> >::value
+ && !std::is_constructible<E, unexpected_type<E2> const & >::value
+ && !std::is_constructible<E, unexpected_type<E2> const >::value
+ && !std::is_convertible< unexpected_type<E2> &, E>::value
+ && !std::is_convertible< unexpected_type<E2> , E>::value
+ && !std::is_convertible< unexpected_type<E2> const &, E>::value
+ && !std::is_convertible< unexpected_type<E2> const , E>::value
+ && !std::is_convertible< E2 const &, E>::value /*=> explicit */
+ )
+ >
+ constexpr explicit unexpected_type( unexpected_type<E2> && error )
+ : m_error( E{ std::move( error.error() ) } )
+ {}
+
+ template< typename E2
+ nsel_REQUIRES_T(
+ std::is_constructible< E, E2>::value
+ && !std::is_constructible<E, unexpected_type<E2> & >::value
+ && !std::is_constructible<E, unexpected_type<E2> >::value
+ && !std::is_constructible<E, unexpected_type<E2> const & >::value
+ && !std::is_constructible<E, unexpected_type<E2> const >::value
+ && !std::is_convertible< unexpected_type<E2> &, E>::value
+ && !std::is_convertible< unexpected_type<E2> , E>::value
+ && !std::is_convertible< unexpected_type<E2> const &, E>::value
+ && !std::is_convertible< unexpected_type<E2> const , E>::value
+ && std::is_convertible< E2 const &, E>::value /*=> non-explicit */
+ )
+ >
+ constexpr /*non-explicit*/ unexpected_type( unexpected_type<E2> && error )
+ : m_error( std::move( error.error() ) )
+ {}
+
+ // x.x.5.2.2 Assignment
+
+ nsel_constexpr14 unexpected_type& operator=( unexpected_type const & ) = default;
+ nsel_constexpr14 unexpected_type& operator=( unexpected_type && ) = default;
+
+ template< typename E2 = E >
+ nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> const & other )
+ {
+ unexpected_type{ other.error() }.swap( *this );
+ return *this;
+ }
+
+ template< typename E2 = E >
+ nsel_constexpr14 unexpected_type & operator=( unexpected_type<E2> && other )
+ {
+ unexpected_type{ std::move( other.error() ) }.swap( *this );
+ return *this;
+ }
+
+ // x.x.5.2.3 Observers
+
+ nsel_constexpr14 E & error() & noexcept
+ {
+ return m_error;
+ }
+
+ constexpr E const & error() const & noexcept
+ {
+ return m_error;
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ nsel_constexpr14 E && error() && noexcept
+ {
+ return std::move( m_error );
+ }
+
+ constexpr E const && error() const && noexcept
+ {
+ return std::move( m_error );
+ }
+
+#endif
+
+ // x.x.5.2.3 Observers - deprecated
+
+ nsel_deprecated("replace value() with error()")
+
+ nsel_constexpr14 E & value() & noexcept
+ {
+ return m_error;
+ }
+
+ nsel_deprecated("replace value() with error()")
+
+ constexpr E const & value() const & noexcept
+ {
+ return m_error;
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ nsel_deprecated("replace value() with error()")
+
+ nsel_constexpr14 E && value() && noexcept
+ {
+ return std::move( m_error );
+ }
+
+ nsel_deprecated("replace value() with error()")
+
+ constexpr E const && value() const && noexcept
+ {
+ return std::move( m_error );
+ }
+
+#endif
+
+ // x.x.5.2.4 Swap
+
+ template< typename U=E >
+ nsel_REQUIRES_R( void,
+ std17::is_swappable<U>::value
+ )
+ swap( unexpected_type & other ) noexcept (
+ std17::is_nothrow_swappable<U>::value
+ )
+ {
+ using std::swap;
+ swap( m_error, other.m_error );
+ }
+
+ // TODO: ??? unexpected_type: in-class friend operator==, !=
+
+private:
+ error_type m_error;
+};
+
+#if nsel_CPP17_OR_GREATER
+
+/// template deduction guide:
+
+template< typename E >
+unexpected_type( E ) -> unexpected_type< E >;
+
+#endif
+
+/// class unexpected_type, std::exception_ptr specialization (P0323R2)
+
+#if !nsel_CONFIG_NO_EXCEPTIONS
+#if nsel_P0323R <= 2
+
+// TODO: Should expected be specialized for particular E types such as exception_ptr and how?
+// See p0323r7 2.1. Ergonomics, http://wg21.link/p0323
+template<>
+class unexpected_type< std::exception_ptr >
+{
+public:
+ using error_type = std::exception_ptr;
+
+ unexpected_type() = delete;
+
+ ~unexpected_type(){}
+
+ explicit unexpected_type( std::exception_ptr const & error )
+ : m_error( error )
+ {}
+
+ explicit unexpected_type(std::exception_ptr && error )
+ : m_error( std::move( error ) )
+ {}
+
+ template< typename E >
+ explicit unexpected_type( E error )
+ : m_error( std::make_exception_ptr( error ) )
+ {}
+
+ std::exception_ptr const & value() const
+ {
+ return m_error;
+ }
+
+ std::exception_ptr & value()
+ {
+ return m_error;
+ }
+
+private:
+ std::exception_ptr m_error;
+};
+
+#endif // nsel_P0323R
+#endif // !nsel_CONFIG_NO_EXCEPTIONS
+
+/// x.x.4, Unexpected equality operators
+
+template< typename E1, typename E2 >
+constexpr bool operator==( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
+{
+ return x.error() == y.error();
+}
+
+template< typename E1, typename E2 >
+constexpr bool operator!=( unexpected_type<E1> const & x, unexpected_type<E2> const & y )
+{
+ return ! ( x == y );
+}
+
+#if nsel_P0323R <= 2
+
+template< typename E >
+constexpr bool operator<( unexpected_type<E> const & x, unexpected_type<E> const & y )
+{
+ return x.error() < y.error();
+}
+
+template< typename E >
+constexpr bool operator>( unexpected_type<E> const & x, unexpected_type<E> const & y )
+{
+ return ( y < x );
+}
+
+template< typename E >
+constexpr bool operator<=( unexpected_type<E> const & x, unexpected_type<E> const & y )
+{
+ return ! ( y < x );
+}
+
+template< typename E >
+constexpr bool operator>=( unexpected_type<E> const & x, unexpected_type<E> const & y )
+{
+ return ! ( x < y );
+}
+
+#endif // nsel_P0323R
+
+/// x.x.5 Specialized algorithms
+
+template< typename E
+ nsel_REQUIRES_T(
+ std17::is_swappable<E>::value
+ )
+>
+void swap( unexpected_type<E> & x, unexpected_type<E> & y) noexcept ( noexcept ( x.swap(y) ) )
+{
+ x.swap( y );
+}
+
+#if nsel_P0323R <= 2
+
+// unexpected: relational operators for std::exception_ptr:
+
+inline constexpr bool operator<( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
+{
+ return false;
+}
+
+inline constexpr bool operator>( unexpected_type<std::exception_ptr> const & /*x*/, unexpected_type<std::exception_ptr> const & /*y*/ )
+{
+ return false;
+}
+
+inline constexpr bool operator<=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
+{
+ return ( x == y );
+}
+
+inline constexpr bool operator>=( unexpected_type<std::exception_ptr> const & x, unexpected_type<std::exception_ptr> const & y )
+{
+ return ( x == y );
+}
+
+#endif // nsel_P0323R
+
+// unexpected: traits
+
+#if nsel_P0323R <= 3
+
+template< typename E>
+struct is_unexpected : std::false_type {};
+
+template< typename E>
+struct is_unexpected< unexpected_type<E> > : std::true_type {};
+
+#endif // nsel_P0323R
+
+// unexpected: factory
+
+// keep make_unexpected() removed in p0323r2 for pre-C++17:
+
+template< typename E>
+nsel_constexpr14 auto
+make_unexpected( E && value ) -> unexpected_type< typename std::decay<E>::type >
+{
+ return unexpected_type< typename std::decay<E>::type >( std::forward<E>(value) );
+}
+
+#if nsel_P0323R <= 3
+
+/*nsel_constexpr14*/ auto inline
+make_unexpected_from_current_exception() -> unexpected_type< std::exception_ptr >
+{
+ return unexpected_type< std::exception_ptr >( std::current_exception() );
+}
+
+#endif // nsel_P0323R
+
+/// x.x.6, x.x.7 expected access error
+
+template< typename E >
+class bad_expected_access;
+
+/// x.x.7 bad_expected_access<void>: expected access error
+
+template <>
+class bad_expected_access< void > : public std::exception
+{
+public:
+ explicit bad_expected_access()
+ : std::exception()
+ {}
+};
+
+/// x.x.6 bad_expected_access: expected access error
+
+#if !nsel_CONFIG_NO_EXCEPTIONS
+
+template< typename E >
+class bad_expected_access : public bad_expected_access< void >
+{
+public:
+ using error_type = E;
+
+ explicit bad_expected_access( error_type error )
+ : m_error( error )
+ {}
+
+ virtual char const * what() const noexcept override
+ {
+ return "bad_expected_access";
+ }
+
+ nsel_constexpr14 error_type & error() &
+ {
+ return m_error;
+ }
+
+ constexpr error_type const & error() const &
+ {
+ return m_error;
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ nsel_constexpr14 error_type && error() &&
+ {
+ return std::move( m_error );
+ }
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( m_error );
+ }
+
+#endif
+
+private:
+ error_type m_error;
+};
+
+#endif // nsel_CONFIG_NO_EXCEPTIONS
+
+/// x.x.8 unexpect tag, in_place_unexpected tag: construct an error
+
+struct unexpect_t{};
+using in_place_unexpected_t = unexpect_t;
+
+nsel_inline17 constexpr unexpect_t unexpect{};
+nsel_inline17 constexpr unexpect_t in_place_unexpected{};
+
+/// class error_traits
+
+#if nsel_CONFIG_NO_EXCEPTIONS
+
+namespace detail {
+ inline bool text( char const * /*text*/ ) { return true; }
+}
+
+template< typename Error >
+struct error_traits
+{
+ static void rethrow( Error const & /*e*/ )
+ {
+#if nsel_CONFIG_NO_EXCEPTIONS_SEH
+ RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
+#else
+ assert( false && detail::text("throw bad_expected_access<Error>{ e };") );
+#endif
+ }
+};
+
+template<>
+struct error_traits< std::exception_ptr >
+{
+ static void rethrow( std::exception_ptr const & /*e*/ )
+ {
+#if nsel_CONFIG_NO_EXCEPTIONS_SEH
+ RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
+#else
+ assert( false && detail::text("throw bad_expected_access<std::exception_ptr>{ e };") );
+#endif
+ }
+};
+
+template<>
+struct error_traits< std::error_code >
+{
+ static void rethrow( std::error_code const & /*e*/ )
+ {
+#if nsel_CONFIG_NO_EXCEPTIONS_SEH
+ RaiseException( EXCEPTION_ACCESS_VIOLATION, EXCEPTION_NONCONTINUABLE, 0, NULL );
+#else
+ assert( false && detail::text("throw std::system_error( e );") );
+#endif
+ }
+};
+
+#else // nsel_CONFIG_NO_EXCEPTIONS
+
+template< typename Error >
+struct error_traits
+{
+ static void rethrow( Error const & e )
+ {
+ throw bad_expected_access<Error>{ e };
+ }
+};
+
+template<>
+struct error_traits< std::exception_ptr >
+{
+ static void rethrow( std::exception_ptr const & e )
+ {
+ std::rethrow_exception( e );
+ }
+};
+
+template<>
+struct error_traits< std::error_code >
+{
+ static void rethrow( std::error_code const & e )
+ {
+ throw std::system_error( e );
+ }
+};
+
+#endif // nsel_CONFIG_NO_EXCEPTIONS
+
+#if nsel_P2505R >= 3
+namespace detail {
+
+// from https://en.cppreference.com/w/cpp/utility/expected/unexpected:
+// "the type of the unexpected value. The type must not be an array type, a non-object type, a specialization of std::unexpected, or a cv-qualified type."
+template< typename T >
+struct valid_unexpected_type : std::integral_constant< bool,
+ std::is_same< T, typename std20::remove_cvref< T >::type >::value
+ && std::is_object< T >::value
+ && !std::is_array< T >::value
+> {};
+
+template< typename T >
+struct valid_unexpected_type< unexpected_type< T > > : std::false_type {};
+
+} // namespace detail
+#endif // nsel_P2505R >= 3
+
+} // namespace expected_lite
+
+// provide nonstd::unexpected_type:
+
+using expected_lite::unexpected_type;
+
+namespace expected_lite {
+
+/// class expected
+
+#if nsel_P0323R <= 2
+template< typename T, typename E = std::exception_ptr >
+class expected
+#else
+template< typename T, typename E >
+class expected
+#endif // nsel_P0323R
+{
+private:
+ template< typename, typename > friend class expected;
+
+public:
+ using value_type = T;
+ using error_type = E;
+ using unexpected_type = nonstd::unexpected_type<E>;
+
+ template< typename U >
+ struct rebind
+ {
+ using type = expected<U, error_type>;
+ };
+
+ // x.x.4.1 constructors
+
+ nsel_REQUIRES_0(
+ std::is_default_constructible<T>::value
+ )
+ nsel_constexpr14 expected()
+ : contained( true )
+ {
+ contained.construct_value();
+ }
+
+ nsel_constexpr14 expected( expected const & ) = default;
+ nsel_constexpr14 expected( expected && ) = default;
+
+ template< typename U, typename G
+ nsel_REQUIRES_T(
+ std::is_constructible< T, U const &>::value
+ && std::is_constructible<E, G const &>::value
+ && !std::is_constructible<T, expected<U, G> & >::value
+ && !std::is_constructible<T, expected<U, G> && >::value
+ && !std::is_constructible<T, expected<U, G> const & >::value
+ && !std::is_constructible<T, expected<U, G> const && >::value
+ && !std::is_convertible< expected<U, G> & , T>::value
+ && !std::is_convertible< expected<U, G> &&, T>::value
+ && !std::is_convertible< expected<U, G> const & , T>::value
+ && !std::is_convertible< expected<U, G> const &&, T>::value
+ && (!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( expected<U, G> const & other )
+ : contained( other.has_value() )
+ {
+ if ( has_value() ) contained.construct_value( T{ other.contained.value() } );
+ else contained.construct_error( E{ other.contained.error() } );
+ }
+
+ template< typename U, typename G
+ nsel_REQUIRES_T(
+ std::is_constructible< T, U const &>::value
+ && std::is_constructible<E, G const &>::value
+ && !std::is_constructible<T, expected<U, G> & >::value
+ && !std::is_constructible<T, expected<U, G> && >::value
+ && !std::is_constructible<T, expected<U, G> const & >::value
+ && !std::is_constructible<T, expected<U, G> const && >::value
+ && !std::is_convertible< expected<U, G> & , T>::value
+ && !std::is_convertible< expected<U, G> &&, T>::value
+ && !std::is_convertible< expected<U, G> const &, T>::value
+ && !std::is_convertible< expected<U, G> const &&, T>::value
+ && !(!std::is_convertible<U const &, T>::value || !std::is_convertible<G const &, E>::value ) /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> const & other )
+ : contained( other.has_value() )
+ {
+ if ( has_value() ) contained.construct_value( other.contained.value() );
+ else contained.construct_error( other.contained.error() );
+ }
+
+ template< typename U, typename G
+ nsel_REQUIRES_T(
+ std::is_constructible< T, U>::value
+ && std::is_constructible<E, G>::value
+ && !std::is_constructible<T, expected<U, G> & >::value
+ && !std::is_constructible<T, expected<U, G> && >::value
+ && !std::is_constructible<T, expected<U, G> const & >::value
+ && !std::is_constructible<T, expected<U, G> const && >::value
+ && !std::is_convertible< expected<U, G> & , T>::value
+ && !std::is_convertible< expected<U, G> &&, T>::value
+ && !std::is_convertible< expected<U, G> const & , T>::value
+ && !std::is_convertible< expected<U, G> const &&, T>::value
+ && (!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( expected<U, G> && other )
+ : contained( other.has_value() )
+ {
+ if ( has_value() ) contained.construct_value( T{ std::move( other.contained.value() ) } );
+ else contained.construct_error( E{ std::move( other.contained.error() ) } );
+ }
+
+ template< typename U, typename G
+ nsel_REQUIRES_T(
+ std::is_constructible< T, U>::value
+ && std::is_constructible<E, G>::value
+ && !std::is_constructible<T, expected<U, G> & >::value
+ && !std::is_constructible<T, expected<U, G> && >::value
+ && !std::is_constructible<T, expected<U, G> const & >::value
+ && !std::is_constructible<T, expected<U, G> const && >::value
+ && !std::is_convertible< expected<U, G> & , T>::value
+ && !std::is_convertible< expected<U, G> &&, T>::value
+ && !std::is_convertible< expected<U, G> const & , T>::value
+ && !std::is_convertible< expected<U, G> const &&, T>::value
+ && !(!std::is_convertible<U, T>::value || !std::is_convertible<G, E>::value ) /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( expected<U, G> && other )
+ : contained( other.has_value() )
+ {
+ if ( has_value() ) contained.construct_value( std::move( other.contained.value() ) );
+ else contained.construct_error( std::move( other.contained.error() ) );
+ }
+
+ template< typename U = T
+ nsel_REQUIRES_T(
+ std::is_copy_constructible<U>::value
+ )
+ >
+ nsel_constexpr14 expected( value_type const & value )
+ : contained( true )
+ {
+ contained.construct_value( value );
+ }
+
+ template< typename U = T
+ nsel_REQUIRES_T(
+ std::is_constructible<T,U&&>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+ && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
+ && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
+ && !std::is_convertible<U&&,T>::value /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( U && value ) noexcept
+ (
+ std::is_nothrow_move_constructible<U>::value &&
+ std::is_nothrow_move_constructible<E>::value
+ )
+ : contained( true )
+ {
+ contained.construct_value( T{ std::forward<U>( value ) } );
+ }
+
+ template< typename U = T
+ nsel_REQUIRES_T(
+ std::is_constructible<T,U&&>::value
+ && !std::is_same<typename std20::remove_cvref<U>::type, nonstd_lite_in_place_t(U)>::value
+ && !std::is_same< expected<T,E> , typename std20::remove_cvref<U>::type>::value
+ && !std::is_same<nonstd::unexpected_type<E>, typename std20::remove_cvref<U>::type>::value
+ && std::is_convertible<U&&,T>::value /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( U && value ) noexcept
+ (
+ std::is_nothrow_move_constructible<U>::value &&
+ std::is_nothrow_move_constructible<E>::value
+ )
+ : contained( true )
+ {
+ contained.construct_value( std::forward<U>( value ) );
+ }
+
+ // construct error:
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G const & >::value
+ && !std::is_convertible< G const &, E>::value /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
+ : contained( false )
+ {
+ contained.construct_error( E{ error.error() } );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G const & >::value
+ && std::is_convertible< G const &, E>::value /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
+ : contained( false )
+ {
+ contained.construct_error( error.error() );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G&& >::value
+ && !std::is_convertible< G&&, E>::value /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
+ : contained( false )
+ {
+ contained.construct_error( E{ std::move( error.error() ) } );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G&& >::value
+ && std::is_convertible< G&&, E>::value /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
+ : contained( false )
+ {
+ contained.construct_error( std::move( error.error() ) );
+ }
+
+ // in-place construction, value
+
+ template< typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<T, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), Args&&... args )
+ : contained( true )
+ {
+ contained.emplace_value( std::forward<Args>( args )... );
+ }
+
+ template< typename U, typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<T, std::initializer_list<U>, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd_lite_in_place_t(T), std::initializer_list<U> il, Args&&... args )
+ : contained( true )
+ {
+ contained.emplace_value( il, std::forward<Args>( args )... );
+ }
+
+ // in-place construction, error
+
+ template< typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
+ : contained( false )
+ {
+ contained.emplace_error( std::forward<Args>( args )... );
+ }
+
+ template< typename U, typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
+ : contained( false )
+ {
+ contained.emplace_error( il, std::forward<Args>( args )... );
+ }
+
+ // x.x.4.2 destructor
+
+ // TODO: ~expected: triviality
+ // Effects: If T is not cv void and is_trivially_destructible_v<T> is false and bool(*this), calls val.~T(). If is_trivially_destructible_v<E> is false and !bool(*this), calls unexpect.~unexpected<E>().
+ // Remarks: If either T is cv void or is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true, then this destructor shall be a trivial destructor.
+
+ ~expected()
+ {
+ if ( has_value() ) contained.destruct_value();
+ else contained.destruct_error();
+ }
+
+ // x.x.4.3 assignment
+
+ expected & operator=( expected const & other )
+ {
+ expected( other ).swap( *this );
+ return *this;
+ }
+
+ expected & operator=( expected && other ) noexcept
+ (
+ std::is_nothrow_move_constructible< T>::value
+ && std::is_nothrow_move_assignable< T>::value
+ && std::is_nothrow_move_constructible<E>::value // added for missing
+ && std::is_nothrow_move_assignable< E>::value ) // nothrow above
+ {
+ expected( std::move( other ) ).swap( *this );
+ return *this;
+ }
+
+ template< typename U
+ nsel_REQUIRES_T(
+ !std::is_same<expected<T,E>, typename std20::remove_cvref<U>::type>::value
+ && std17::conjunction<std::is_scalar<T>, std::is_same<T, std::decay<U>> >::value
+ && std::is_constructible<T ,U>::value
+ && std::is_assignable< T&,U>::value
+ && std::is_nothrow_move_constructible<E>::value )
+ >
+ expected & operator=( U && value )
+ {
+ expected( std::forward<U>( value ) ).swap( *this );
+ return *this;
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G const&>::value &&
+ std::is_copy_constructible<G>::value // TODO: std::is_nothrow_copy_constructible<G>
+ && std::is_copy_assignable<G>::value
+ )
+ >
+ expected & operator=( nonstd::unexpected_type<G> const & error )
+ {
+ expected( unexpect, error.error() ).swap( *this );
+ return *this;
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_constructible<E, G&&>::value &&
+ std::is_move_constructible<G>::value // TODO: std::is_nothrow_move_constructible<G>
+ && std::is_move_assignable<G>::value
+ )
+ >
+ expected & operator=( nonstd::unexpected_type<G> && error )
+ {
+ expected( unexpect, std::move( error.error() ) ).swap( *this );
+ return *this;
+ }
+
+ template< typename... Args
+ nsel_REQUIRES_T(
+ std::is_nothrow_constructible<T, Args&&...>::value
+ )
+ >
+ value_type & emplace( Args &&... args )
+ {
+ expected( nonstd_lite_in_place(T), std::forward<Args>(args)... ).swap( *this );
+ return value();
+ }
+
+ template< typename U, typename... Args
+ nsel_REQUIRES_T(
+ std::is_nothrow_constructible<T, std::initializer_list<U>&, Args&&...>::value
+ )
+ >
+ value_type & emplace( std::initializer_list<U> il, Args &&... args )
+ {
+ expected( nonstd_lite_in_place(T), il, std::forward<Args>(args)... ).swap( *this );
+ return value();
+ }
+
+ // x.x.4.4 swap
+
+ template< typename U=T, typename G=E >
+ nsel_REQUIRES_R( void,
+ std17::is_swappable< U>::value
+ && std17::is_swappable<G>::value
+ && ( std::is_move_constructible<U>::value || std::is_move_constructible<G>::value )
+ )
+ swap( expected & other ) noexcept
+ (
+ std::is_nothrow_move_constructible<T>::value && std17::is_nothrow_swappable<T&>::value &&
+ std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
+ )
+ {
+ using std::swap;
+
+ if ( bool(*this) && bool(other) ) { swap( contained.value(), other.contained.value() ); }
+ else if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
+ else if ( bool(*this) && ! bool(other) ) { error_type t( std::move( other.error() ) );
+ other.contained.destruct_error();
+ other.contained.construct_value( std::move( contained.value() ) );
+ contained.destruct_value();
+ contained.construct_error( std::move( t ) );
+ bool has_value = contained.has_value();
+ bool other_has_value = other.has_value();
+ other.contained.set_has_value(has_value);
+ contained.set_has_value(other_has_value);
+ }
+ else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
+ }
+
+ // x.x.4.5 observers
+
+ constexpr value_type const * operator ->() const
+ {
+ return assert( has_value() ), contained.value_ptr();
+ }
+
+ value_type * operator ->()
+ {
+ return assert( has_value() ), contained.value_ptr();
+ }
+
+ constexpr value_type const & operator *() const &
+ {
+ return assert( has_value() ), contained.value();
+ }
+
+ value_type & operator *() &
+ {
+ return assert( has_value() ), contained.value();
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ constexpr value_type const && operator *() const &&
+ {
+ return std::move( ( assert( has_value() ), contained.value() ) );
+ }
+
+ nsel_constexpr14 value_type && operator *() &&
+ {
+ return std::move( ( assert( has_value() ), contained.value() ) );
+ }
+
+#endif
+
+ constexpr explicit operator bool() const noexcept
+ {
+ return has_value();
+ }
+
+ constexpr bool has_value() const noexcept
+ {
+ return contained.has_value();
+ }
+
+ nsel_DISABLE_MSVC_WARNINGS( 4702 ) // warning C4702: unreachable code, see issue 65.
+
+ constexpr value_type const & value() const &
+ {
+ return has_value()
+ ? ( contained.value() )
+ : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
+ }
+
+ value_type & value() &
+ {
+ return has_value()
+ ? ( contained.value() )
+ : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() );
+ }
+ nsel_RESTORE_MSVC_WARNINGS()
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ constexpr value_type const && value() const &&
+ {
+ return std::move( has_value()
+ ? ( contained.value() )
+ : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
+ }
+
+ nsel_constexpr14 value_type && value() &&
+ {
+ return std::move( has_value()
+ ? ( contained.value() )
+ : ( error_traits<error_type>::rethrow( contained.error() ), contained.value() ) );
+ }
+
+#endif
+
+ constexpr error_type const & error() const &
+ {
+ return assert( ! has_value() ), contained.error();
+ }
+
+ error_type & error() &
+ {
+ return assert( ! has_value() ), contained.error();
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( ( assert( ! has_value() ), contained.error() ) );
+ }
+
+ error_type && error() &&
+ {
+ return std::move( ( assert( ! has_value() ), contained.error() ) );
+ }
+
+#endif
+
+ constexpr unexpected_type get_unexpected() const
+ {
+ return make_unexpected( contained.error() );
+ }
+
+ template< typename Ex >
+ bool has_exception() const
+ {
+ using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
+ return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
+ }
+
+ template< typename U
+ nsel_REQUIRES_T(
+ std::is_copy_constructible< T>::value
+ && std::is_convertible<U&&, T>::value
+ )
+ >
+ value_type value_or( U && v ) const &
+ {
+ return has_value()
+ ? contained.value()
+ : static_cast<T>( std::forward<U>( v ) );
+ }
+
+ template< typename U
+ nsel_REQUIRES_T(
+ std::is_move_constructible< T>::value
+ && std::is_convertible<U&&, T>::value
+ )
+ >
+ value_type value_or( U && v ) &&
+ {
+ return has_value()
+ ? std::move( contained.value() )
+ : static_cast<T>( std::forward<U>( v ) );
+ }
+
+#if nsel_P2505R >= 4
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_copy_constructible< E >::value
+ && std::is_convertible< G, E >::value
+ )
+ >
+ nsel_constexpr error_type error_or( G && e ) const &
+ {
+ return has_value()
+ ? static_cast< E >( std::forward< G >( e ) )
+ : contained.error();
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_move_constructible< E >::value
+ && std::is_convertible< G, E >::value
+ )
+ >
+ nsel_constexpr14 error_type error_or( G && e ) &&
+ {
+ return has_value()
+ ? static_cast< E >( std::forward< G >( e ) )
+ : std::move( contained.error() );
+ }
+#endif // nsel_P2505R >= 4
+
+#if nsel_P2505R >= 3
+ // Monadic operations (P2505)
+ template< typename F
+ nsel_REQUIRES_T(
+ detail::is_expected < detail::invoke_result_nocvref_t< F, value_type & > > ::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type & >::error_type, error_type >::value
+ && std::is_constructible< error_type, error_type & >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type & > and_then( F && f ) &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, value_type & >( detail::invoke( std::forward< F >( f ), value() ) )
+ : detail::invoke_result_nocvref_t< F, value_type & >( unexpect, error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const value_type & > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value
+ && std::is_constructible< error_type, const error_type & >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type & > and_then( F && f ) const &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const value_type & >( detail::invoke( std::forward< F >( f ), value() ) )
+ : detail::invoke_result_nocvref_t< F, const value_type & >( unexpect, error() );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, value_type && > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, value_type && >::error_type, error_type >::value
+ && std::is_constructible< error_type, error_type && >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, value_type && > and_then( F && f ) &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) )
+ : detail::invoke_result_nocvref_t< F, value_type && >( unexpect, std::move( error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const value_type && > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, const value_type & >::error_type, error_type >::value
+ && std::is_constructible< error_type, const error_type && >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const value_type && > and_then( F && f ) const &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const value_type && >( detail::invoke( std::forward< F >( f ), std::move( value() ) ) )
+ : detail::invoke_result_nocvref_t< F, const value_type && >( unexpect, std::move( error() ) );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, error_type & > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type, value_type >::value
+ && std::is_constructible< value_type, value_type & >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, error_type & >( value() )
+ : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type & > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type, value_type >::value
+ && std::is_constructible< value_type, const value_type & >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const error_type & >( value() )
+ : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, error_type && > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type, value_type >::value
+ && std::is_constructible< value_type, value_type && >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, error_type && >( std::move( value() ) )
+ : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type && > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type, value_type >::value
+ && std::is_constructible< value_type, const value_type && >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const error_type && >( std::move( value() ) )
+ : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type & >::value
+ && !std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value
+ && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type & > >::value
+ )
+ >
+ nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type & >, error_type > transform( F && f ) &
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F, value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type & >::value
+ && std::is_void< detail::transform_invoke_result_t< F, value_type & > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, error_type > transform( F && f ) &
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type & >::value
+ && !std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value
+ && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type & > >::value
+ )
+ >
+ nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type & >, error_type > transform( F && f ) const &
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F, const value_type & >, error_type >( detail::invoke( std::forward< F >( f ), **this ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type & >::value
+ && std::is_void< detail::transform_invoke_result_t< F, const value_type & > >::value
+ )
+ >
+ nsel_constexpr expected< void, error_type > transform( F && f ) const &
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type && >::value
+ && !std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value
+ && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, value_type && > >::value
+ )
+ >
+ nsel_constexpr14 expected< detail::transform_invoke_result_t< F, value_type && >, error_type > transform( F && f ) &&
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F, value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) )
+ : make_unexpected( std::move( error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type && >::value
+ && std::is_void< detail::transform_invoke_result_t< F, value_type && > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, error_type > transform( F && f ) &&
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
+ : make_unexpected( std::move( error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type && >::value
+ && !std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value
+ && detail::valid_expected_value_type< detail::transform_invoke_result_t< F, const value_type && > >::value
+ )
+ >
+ nsel_constexpr expected< detail::transform_invoke_result_t< F, const value_type && >, error_type > transform( F && f ) const &&
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F, const value_type && >, error_type >( detail::invoke( std::forward< F >( f ), std::move( **this ) ) )
+ : make_unexpected( std::move( error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type && >::value
+ && std::is_void< detail::transform_invoke_result_t< F, const value_type && > >::value
+ )
+ >
+ nsel_constexpr expected< void, error_type > transform( F && f ) const &&
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ), **this ), expected< void, error_type >() )
+ : make_unexpected( std::move( error() ) );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type & > >::value
+ && std::is_constructible< value_type, value_type & >::value
+ )
+ >
+ nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) &
+ {
+ return has_value()
+ ? expected< value_type, detail::transform_invoke_result_t< F, error_type & > >( in_place, **this )
+ : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type & > >::value
+ && std::is_constructible< value_type, const value_type & >::value
+ )
+ >
+ nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const &
+ {
+ return has_value()
+ ? expected< value_type, detail::transform_invoke_result_t< F, const error_type & > >( in_place, **this )
+ : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type && > >::value
+ && std::is_constructible< value_type, value_type && >::value
+ )
+ >
+ nsel_constexpr14 expected< value_type, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) &&
+ {
+ return has_value()
+ ? expected< value_type, detail::transform_invoke_result_t< F, error_type && > >( in_place, std::move( **this ) )
+ : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type && > >::value
+ && std::is_constructible< value_type, const value_type && >::value
+ )
+ >
+ nsel_constexpr expected< value_type, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const &&
+ {
+ return has_value()
+ ? expected< value_type, detail::transform_invoke_result_t< F, const error_type && > >( in_place, std::move( **this ) )
+ : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+#endif
+#endif // nsel_P2505R >= 3
+ // unwrap()
+
+// template <class U, class E>
+// constexpr expected<U,E> expected<expected<U,E>,E>::unwrap() const&;
+
+// template <class T, class E>
+// constexpr expected<T,E> expected<T,E>::unwrap() const&;
+
+// template <class U, class E>
+// expected<U,E> expected<expected<U,E>, E>::unwrap() &&;
+
+// template <class T, class E>
+// template expected<T,E> expected<T,E>::unwrap() &&;
+
+ // factories
+
+// template< typename Ex, typename F>
+// expected<T,E> catch_exception(F&& f);
+
+// template< typename F>
+// expected<decltype(func(declval<T>())),E> map(F&& func) ;
+
+// template< typename F>
+// 'see below' bind(F&& func);
+
+// template< typename F>
+// expected<T,E> catch_error(F&& f);
+
+// template< typename F>
+// 'see below' then(F&& func);
+
+private:
+ detail::storage_t
+ <
+ T
+ ,E
+ , std::is_copy_constructible<T>::value && std::is_copy_constructible<E>::value
+ , std::is_move_constructible<T>::value && std::is_move_constructible<E>::value
+ >
+ contained;
+};
+
+/// class expected, void specialization
+
+template< typename E >
+class expected<void, E>
+{
+private:
+ template< typename, typename > friend class expected;
+
+public:
+ using value_type = void;
+ using error_type = E;
+ using unexpected_type = nonstd::unexpected_type<E>;
+
+ // x.x.4.1 constructors
+
+ constexpr expected() noexcept
+ : contained( true )
+ {}
+
+ nsel_constexpr14 expected( expected const & other ) = default;
+ nsel_constexpr14 expected( expected && other ) = default;
+
+ constexpr explicit expected( nonstd_lite_in_place_t(void) )
+ : contained( true )
+ {}
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ !std::is_convertible<G const &, E>::value /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> const & error )
+ : contained( false )
+ {
+ contained.construct_error( E{ error.error() } );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_convertible<G const &, E>::value /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> const & error )
+ : contained( false )
+ {
+ contained.construct_error( error.error() );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ !std::is_convertible<G&&, E>::value /*=> explicit */
+ )
+ >
+ nsel_constexpr14 explicit expected( nonstd::unexpected_type<G> && error )
+ : contained( false )
+ {
+ contained.construct_error( E{ std::move( error.error() ) } );
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_convertible<G&&, E>::value /*=> non-explicit */
+ )
+ >
+ nsel_constexpr14 /*non-explicit*/ expected( nonstd::unexpected_type<G> && error )
+ : contained( false )
+ {
+ contained.construct_error( std::move( error.error() ) );
+ }
+
+ template< typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( unexpect_t, Args&&... args )
+ : contained( false )
+ {
+ contained.emplace_error( std::forward<Args>( args )... );
+ }
+
+ template< typename U, typename... Args
+ nsel_REQUIRES_T(
+ std::is_constructible<E, std::initializer_list<U>, Args&&...>::value
+ )
+ >
+ nsel_constexpr14 explicit expected( unexpect_t, std::initializer_list<U> il, Args&&... args )
+ : contained( false )
+ {
+ contained.emplace_error( il, std::forward<Args>( args )... );
+ }
+
+ // destructor
+
+ ~expected()
+ {
+ if ( ! has_value() )
+ {
+ contained.destruct_error();
+ }
+ }
+
+ // x.x.4.3 assignment
+
+ expected & operator=( expected const & other )
+ {
+ expected( other ).swap( *this );
+ return *this;
+ }
+
+ expected & operator=( expected && other ) noexcept
+ (
+ std::is_nothrow_move_assignable<E>::value &&
+ std::is_nothrow_move_constructible<E>::value )
+ {
+ expected( std::move( other ) ).swap( *this );
+ return *this;
+ }
+
+ void emplace()
+ {
+ expected().swap( *this );
+ }
+
+ // x.x.4.4 swap
+
+ template< typename G = E >
+ nsel_REQUIRES_R( void,
+ std17::is_swappable<G>::value
+ && std::is_move_constructible<G>::value
+ )
+ swap( expected & other ) noexcept
+ (
+ std::is_nothrow_move_constructible<E>::value && std17::is_nothrow_swappable<E&>::value
+ )
+ {
+ using std::swap;
+
+ if ( ! bool(*this) && ! bool(other) ) { swap( contained.error(), other.contained.error() ); }
+ else if ( bool(*this) && ! bool(other) ) { contained.construct_error( std::move( other.error() ) );
+ bool has_value = contained.has_value();
+ bool other_has_value = other.has_value();
+ other.contained.set_has_value(has_value);
+ contained.set_has_value(other_has_value);
+ }
+ else if ( ! bool(*this) && bool(other) ) { other.swap( *this ); }
+ }
+
+ // x.x.4.5 observers
+
+ constexpr explicit operator bool() const noexcept
+ {
+ return has_value();
+ }
+
+ constexpr bool has_value() const noexcept
+ {
+ return contained.has_value();
+ }
+
+ void value() const
+ {
+ if ( ! has_value() )
+ {
+ error_traits<error_type>::rethrow( contained.error() );
+ }
+ }
+
+ constexpr error_type const & error() const &
+ {
+ return assert( ! has_value() ), contained.error();
+ }
+
+ error_type & error() &
+ {
+ return assert( ! has_value() ), contained.error();
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+
+ constexpr error_type const && error() const &&
+ {
+ return std::move( ( assert( ! has_value() ), contained.error() ) );
+ }
+
+ error_type && error() &&
+ {
+ return std::move( ( assert( ! has_value() ), contained.error() ) );
+ }
+
+#endif
+
+ constexpr unexpected_type get_unexpected() const
+ {
+ return make_unexpected( contained.error() );
+ }
+
+ template< typename Ex >
+ bool has_exception() const
+ {
+ using ContainedEx = typename std::remove_reference< decltype( get_unexpected().value() ) >::type;
+ return ! has_value() && std::is_base_of< Ex, ContainedEx>::value;
+ }
+
+#if nsel_P2505R >= 4
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_copy_constructible< E >::value
+ && std::is_convertible< G, E >::value
+ )
+ >
+ nsel_constexpr error_type error_or( G && e ) const &
+ {
+ return has_value()
+ ? static_cast< E >( std::forward< G >( e ) )
+ : contained.error();
+ }
+
+ template< typename G = E
+ nsel_REQUIRES_T(
+ std::is_move_constructible< E >::value
+ && std::is_convertible< G, E >::value
+ )
+ >
+ nsel_constexpr14 error_type error_or( G && e ) &&
+ {
+ return has_value()
+ ? static_cast< E >( std::forward< G >( e ) )
+ : std::move( contained.error() );
+ }
+#endif // nsel_P2505R >= 4
+
+#if nsel_P2505R >= 3
+ // Monadic operations (P2505)
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
+ && std::is_constructible< error_type, error_type & >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
+ : detail::invoke_result_nocvref_t< F >( unexpect, error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
+ && std::is_constructible< error_type, const error_type & >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
+ : detail::invoke_result_nocvref_t< F >( unexpect, error() );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
+ && std::is_constructible< error_type, error_type && >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F > and_then( F && f ) &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
+ : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F > >::value
+ && std::is_same< typename detail::invoke_result_nocvref_t< F >::error_type, error_type >::value
+ && std::is_constructible< error_type, const error_type && >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F > and_then( F && f ) const &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F >( detail::invoke( std::forward< F >( f ) ) )
+ : detail::invoke_result_nocvref_t< F >( unexpect, std::move( error() ) );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, error_type & > >::value
+ && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type & >::value_type >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type & > or_else( F && f ) &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, error_type & >()
+ : detail::invoke_result_nocvref_t< F, error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type & > >::value
+ && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type & >::value_type >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type & > or_else( F && f ) const &
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const error_type & >()
+ : detail::invoke_result_nocvref_t< F, const error_type & >( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, error_type && > >::value
+ && std::is_void< typename detail::invoke_result_nocvref_t< F, error_type && >::value_type >::value
+ )
+ >
+ nsel_constexpr14 detail::invoke_result_nocvref_t< F, error_type && > or_else( F && f ) &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, error_type && >()
+ : detail::invoke_result_nocvref_t< F, error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::is_expected< detail::invoke_result_nocvref_t< F, const error_type && > >::value
+ && std::is_void< typename detail::invoke_result_nocvref_t< F, const error_type && >::value_type >::value
+ )
+ >
+ nsel_constexpr detail::invoke_result_nocvref_t< F, const error_type && > or_else( F && f ) const &&
+ {
+ return has_value()
+ ? detail::invoke_result_nocvref_t< F, const error_type && >()
+ : detail::invoke_result_nocvref_t< F, const error_type && >( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type & >::value
+ && !std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) &
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type & >::value
+ && std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, error_type > transform( F && f ) &
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type & >::value
+ && !std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const &
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type & >::value
+ && std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr expected< void, error_type > transform( F && f ) const &
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type && >::value
+ && !std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr14 expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) &&
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, error_type && >::value
+ && std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, error_type > transform( F && f ) &&
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type && >::value
+ && !std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr expected< detail::transform_invoke_result_t< F >, error_type > transform( F && f ) const &&
+ {
+ return has_value()
+ ? expected< detail::transform_invoke_result_t< F >, error_type >( detail::invoke( std::forward< F >( f ) ) )
+ : make_unexpected( error() );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ std::is_constructible< error_type, const error_type && >::value
+ && std::is_void< detail::transform_invoke_result_t< F > >::value
+ )
+ >
+ nsel_constexpr expected< void, error_type > transform( F && f ) const &&
+ {
+ return has_value()
+ ? ( detail::invoke( std::forward< F >( f ) ), expected< void, error_type >() )
+ : make_unexpected( error() );
+ }
+#endif
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type & > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type & > > transform_error( F && f ) &
+ {
+ return has_value()
+ ? expected< void, detail::transform_invoke_result_t< F, error_type & > >()
+ : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type & > >::value
+ )
+ >
+ nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type & > > transform_error( F && f ) const &
+ {
+ return has_value()
+ ? expected< void, detail::transform_invoke_result_t< F, const error_type & > >()
+ : make_unexpected( detail::invoke( std::forward< F >( f ), error() ) );
+ }
+
+#if !nsel_COMPILER_GNUC_VERSION || nsel_COMPILER_GNUC_VERSION >= 490
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, error_type && > >::value
+ )
+ >
+ nsel_constexpr14 expected< void, detail::transform_invoke_result_t< F, error_type && > > transform_error( F && f ) &&
+ {
+ return has_value()
+ ? expected< void, detail::transform_invoke_result_t< F, error_type && > >()
+ : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+
+ template<typename F
+ nsel_REQUIRES_T(
+ detail::valid_unexpected_type< detail::transform_invoke_result_t< F, const error_type && > >::value
+ )
+ >
+ nsel_constexpr expected< void, detail::transform_invoke_result_t< F, const error_type && > > transform_error( F && f ) const &&
+ {
+ return has_value()
+ ? expected< void, detail::transform_invoke_result_t< F, const error_type && > >()
+ : make_unexpected( detail::invoke( std::forward< F >( f ), std::move( error() ) ) );
+ }
+#endif
+#endif // nsel_P2505R >= 3
+
+// template constexpr 'see below' unwrap() const&;
+//
+// template 'see below' unwrap() &&;
+
+ // factories
+
+// template< typename Ex, typename F>
+// expected<void,E> catch_exception(F&& f);
+//
+// template< typename F>
+// expected<decltype(func()), E> map(F&& func) ;
+//
+// template< typename F>
+// 'see below' bind(F&& func) ;
+//
+// template< typename F>
+// expected<void,E> catch_error(F&& f);
+//
+// template< typename F>
+// 'see below' then(F&& func);
+
+private:
+ detail::storage_t
+ <
+ void
+ , E
+ , std::is_copy_constructible<E>::value
+ , std::is_move_constructible<E>::value
+ >
+ contained;
+};
+
+// x.x.4.6 expected<>: comparison operators
+
+template< typename T1, typename E1, typename T2, typename E2
+ nsel_REQUIRES_T(
+ !std::is_void<T1>::value && !std::is_void<T2>::value
+ )
+>
+constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y )
+{
+ return bool(x) != bool(y) ? false : bool(x) ? *x == *y : x.error() == y.error();
+}
+
+template< typename T1, typename E1, typename T2, typename E2
+ nsel_REQUIRES_T(
+ std::is_void<T1>::value && std::is_void<T2>::value
+ )
+>
+constexpr bool operator==( expected<T1,E1> const & x, expected<T2,E2> const & y )
+{
+ return bool(x) != bool(y) ? false : bool(x) || static_cast<bool>( x.error() == y.error() );
+}
+
+template< typename T1, typename E1, typename T2, typename E2 >
+constexpr bool operator!=( expected<T1,E1> const & x, expected<T2,E2> const & y )
+{
+ return !(x == y);
+}
+
+#if nsel_P0323R <= 2
+
+template< typename T, typename E >
+constexpr bool operator<( expected<T,E> const & x, expected<T,E> const & y )
+{
+ return (!y) ? false : (!x) ? true : *x < *y;
+}
+
+template< typename T, typename E >
+constexpr bool operator>( expected<T,E> const & x, expected<T,E> const & y )
+{
+ return (y < x);
+}
+
+template< typename T, typename E >
+constexpr bool operator<=( expected<T,E> const & x, expected<T,E> const & y )
+{
+ return !(y < x);
+}
+
+template< typename T, typename E >
+constexpr bool operator>=( expected<T,E> const & x, expected<T,E> const & y )
+{
+ return !(x < y);
+}
+
+#endif
+
+// x.x.4.7 expected: comparison with T
+
+template< typename T1, typename E1, typename T2
+ nsel_REQUIRES_T(
+ !std::is_void<T1>::value
+ )
+>
+constexpr bool operator==( expected<T1,E1> const & x, T2 const & v )
+{
+ return bool(x) ? *x == v : false;
+}
+
+template< typename T1, typename E1, typename T2
+ nsel_REQUIRES_T(
+ !std::is_void<T1>::value
+ )
+>
+constexpr bool operator==(T2 const & v, expected<T1,E1> const & x )
+{
+ return bool(x) ? v == *x : false;
+}
+
+template< typename T1, typename E1, typename T2 >
+constexpr bool operator!=( expected<T1,E1> const & x, T2 const & v )
+{
+ return bool(x) ? *x != v : true;
+}
+
+template< typename T1, typename E1, typename T2 >
+constexpr bool operator!=( T2 const & v, expected<T1,E1> const & x )
+{
+ return bool(x) ? v != *x : true;
+}
+
+#if nsel_P0323R <= 2
+
+template< typename T, typename E >
+constexpr bool operator<( expected<T,E> const & x, T const & v )
+{
+ return bool(x) ? *x < v : true;
+}
+
+template< typename T, typename E >
+constexpr bool operator<( T const & v, expected<T,E> const & x )
+{
+ return bool(x) ? v < *x : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator>( T const & v, expected<T,E> const & x )
+{
+ return bool(x) ? *x < v : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator>( expected<T,E> const & x, T const & v )
+{
+ return bool(x) ? v < *x : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator<=( T const & v, expected<T,E> const & x )
+{
+ return bool(x) ? ! ( *x < v ) : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator<=( expected<T,E> const & x, T const & v )
+{
+ return bool(x) ? ! ( v < *x ) : true;
+}
+
+template< typename T, typename E >
+constexpr bool operator>=( expected<T,E> const & x, T const & v )
+{
+ return bool(x) ? ! ( *x < v ) : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator>=( T const & v, expected<T,E> const & x )
+{
+ return bool(x) ? ! ( v < *x ) : true;
+}
+
+#endif // nsel_P0323R
+
+// x.x.4.8 expected: comparison with unexpected_type
+
+template< typename T1, typename E1 , typename E2 >
+constexpr bool operator==( expected<T1,E1> const & x, unexpected_type<E2> const & u )
+{
+ return (!x) ? x.get_unexpected() == u : false;
+}
+
+template< typename T1, typename E1 , typename E2 >
+constexpr bool operator==( unexpected_type<E2> const & u, expected<T1,E1> const & x )
+{
+ return ( x == u );
+}
+
+template< typename T1, typename E1 , typename E2 >
+constexpr bool operator!=( expected<T1,E1> const & x, unexpected_type<E2> const & u )
+{
+ return ! ( x == u );
+}
+
+template< typename T1, typename E1 , typename E2 >
+constexpr bool operator!=( unexpected_type<E2> const & u, expected<T1,E1> const & x )
+{
+ return ! ( x == u );
+}
+
+#if nsel_P0323R <= 2
+
+template< typename T, typename E >
+constexpr bool operator<( expected<T,E> const & x, unexpected_type<E> const & u )
+{
+ return (!x) ? ( x.get_unexpected() < u ) : false;
+}
+
+template< typename T, typename E >
+constexpr bool operator<( unexpected_type<E> const & u, expected<T,E> const & x )
+{
+ return (!x) ? ( u < x.get_unexpected() ) : true ;
+}
+
+template< typename T, typename E >
+constexpr bool operator>( expected<T,E> const & x, unexpected_type<E> const & u )
+{
+ return ( u < x );
+}
+
+template< typename T, typename E >
+constexpr bool operator>( unexpected_type<E> const & u, expected<T,E> const & x )
+{
+ return ( x < u );
+}
+
+template< typename T, typename E >
+constexpr bool operator<=( expected<T,E> const & x, unexpected_type<E> const & u )
+{
+ return ! ( u < x );
+}
+
+template< typename T, typename E >
+constexpr bool operator<=( unexpected_type<E> const & u, expected<T,E> const & x)
+{
+ return ! ( x < u );
+}
+
+template< typename T, typename E >
+constexpr bool operator>=( expected<T,E> const & x, unexpected_type<E> const & u )
+{
+ return ! ( u > x );
+}
+
+template< typename T, typename E >
+constexpr bool operator>=( unexpected_type<E> const & u, expected<T,E> const & x )
+{
+ return ! ( x > u );
+}
+
+#endif // nsel_P0323R
+
+/// x.x.x Specialized algorithms
+
+template< typename T, typename E
+ nsel_REQUIRES_T(
+ ( std::is_void<T>::value || std::is_move_constructible<T>::value )
+ && std::is_move_constructible<E>::value
+ && std17::is_swappable<T>::value
+ && std17::is_swappable<E>::value )
+>
+void swap( expected<T,E> & x, expected<T,E> & y ) noexcept ( noexcept ( x.swap(y) ) )
+{
+ x.swap( y );
+}
+
+#if nsel_P0323R <= 3
+
+template< typename T >
+constexpr auto make_expected( T && v ) -> expected< typename std::decay<T>::type >
+{
+ return expected< typename std::decay<T>::type >( std::forward<T>( v ) );
+}
+
+// expected<void> specialization:
+
+auto inline make_expected() -> expected<void>
+{
+ return expected<void>( in_place );
+}
+
+template< typename T >
+constexpr auto make_expected_from_current_exception() -> expected<T>
+{
+ return expected<T>( make_unexpected_from_current_exception() );
+}
+
+template< typename T >
+auto make_expected_from_exception( std::exception_ptr v ) -> expected<T>
+{
+ return expected<T>( unexpected_type<std::exception_ptr>( std::forward<std::exception_ptr>( v ) ) );
+}
+
+template< typename T, typename E >
+constexpr auto make_expected_from_error( E e ) -> expected<T, typename std::decay<E>::type>
+{
+ return expected<T, typename std::decay<E>::type>( make_unexpected( e ) );
+}
+
+template< typename F
+ nsel_REQUIRES_T( ! std::is_same<typename std::result_of<F()>::type, void>::value )
+>
+/*nsel_constexpr14*/
+auto make_expected_from_call( F f ) -> expected< typename std::result_of<F()>::type >
+{
+ try
+ {
+ return make_expected( f() );
+ }
+ catch (...)
+ {
+ return make_unexpected_from_current_exception();
+ }
+}
+
+template< typename F
+ nsel_REQUIRES_T( std::is_same<typename std::result_of<F()>::type, void>::value )
+>
+/*nsel_constexpr14*/
+auto make_expected_from_call( F f ) -> expected<void>
+{
+ try
+ {
+ f();
+ return make_expected();
+ }
+ catch (...)
+ {
+ return make_unexpected_from_current_exception();
+ }
+}
+
+#endif // nsel_P0323R
+
+} // namespace expected_lite
+
+using namespace expected_lite;
+
+// using expected_lite::expected;
+// using ...
+
+} // namespace nonstd
+
+namespace std {
+
+// expected: hash support
+
+template< typename T, typename E >
+struct hash< nonstd::expected<T,E> >
+{
+ using result_type = std::size_t;
+ using argument_type = nonstd::expected<T,E>;
+
+ constexpr result_type operator()(argument_type const & arg) const
+ {
+ return arg ? std::hash<T>{}(*arg) : result_type{};
+ }
+};
+
+// TBD - ?? remove? see spec.
+template< typename T, typename E >
+struct hash< nonstd::expected<T&,E> >
+{
+ using result_type = std::size_t;
+ using argument_type = nonstd::expected<T&,E>;
+
+ constexpr result_type operator()(argument_type const & arg) const
+ {
+ return arg ? std::hash<T>{}(*arg) : result_type{};
+ }
+};
+
+// TBD - implement
+// bool(e), hash<expected<void,E>>()(e) shall evaluate to the hashing true;
+// otherwise it evaluates to an unspecified value if E is exception_ptr or
+// a combination of hashing false and hash<E>()(e.error()).
+
+template< typename E >
+struct hash< nonstd::expected<void,E> >
+{
+};
+
+} // namespace std
+
+namespace nonstd {
+
+// void unexpected() is deprecated && removed in C++17
+
+#if nsel_CPP17_OR_GREATER || nsel_COMPILER_MSVC_VERSION > 141
+template< typename E >
+using unexpected = unexpected_type<E>;
+#endif
+
+} // namespace nonstd
+
+#undef nsel_REQUIRES
+#undef nsel_REQUIRES_0
+#undef nsel_REQUIRES_T
+
+nsel_RESTORE_WARNINGS()
+
+#endif // nsel_USES_STD_EXPECTED
+
+#endif // NONSTD_EXPECTED_LITE_HPP
diff --git a/contrib/restricted/expected-lite/ya.make b/contrib/restricted/expected-lite/ya.make
new file mode 100644
index 0000000000..21762a23a3
--- /dev/null
+++ b/contrib/restricted/expected-lite/ya.make
@@ -0,0 +1,13 @@
+# Generated by devtools/yamaker from nixpkgs 22.11.
+
+LIBRARY()
+
+LICENSE(BSL-1.0)
+
+LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
+
+VERSION(0.8.0)
+
+ORIGINAL_SOURCE(https://github.com/martinmoene/expected-lite/archive/v0.8.0.tar.gz)
+
+END()