mmdeploy/third_party/outcome/outcome-experimental.hpp

10982 lines
470 KiB
C++

/* A less simple result type
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (17 commits)
File Created: Apr 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_EXPERIMENTAL_STATUS_OUTCOME_HPP
#define OUTCOME_EXPERIMENTAL_STATUS_OUTCOME_HPP
/* A less simple result type
(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: June 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_OUTCOME_HPP
#define OUTCOME_BASIC_OUTCOME_HPP
/* Configure Outcome with QuickCppLib
(C) 2015-2021 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: August 2015
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_V2_CONFIG_HPP
#define OUTCOME_V2_CONFIG_HPP
/* Sets Outcome version
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/*! AWAITING HUGO JSON CONVERSION TOOL */
#define OUTCOME_VERSION_MAJOR 2
/*! AWAITING HUGO JSON CONVERSION TOOL */
#define OUTCOME_VERSION_MINOR 2
/*! AWAITING HUGO JSON CONVERSION TOOL */
#define OUTCOME_VERSION_PATCH 0
/*! AWAITING HUGO JSON CONVERSION TOOL */
#define OUTCOME_VERSION_REVISION 0 // Revision version for cmake and DLL version stamping
/*! AWAITING HUGO JSON CONVERSION TOOL */
#ifndef OUTCOME_DISABLE_ABI_PERMUTATION
#define OUTCOME_UNSTABLE_VERSION
#endif
// Pull in detection of __MINGW64_VERSION_MAJOR
#if defined(__MINGW32__) && !0L
#include <_mingw.h>
#endif
/* Configure QuickCppLib
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef QUICKCPPLIB_CONFIG_HPP
#define QUICKCPPLIB_CONFIG_HPP
/* Provides SG-10 feature checking for all C++ compilers
(C) 2014-2017 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
File Created: Nov 2014
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef QUICKCPPLIB_HAS_FEATURE_H
#define QUICKCPPLIB_HAS_FEATURE_H
#if __cplusplus >= 201103L
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_alignas)
////#define __cpp_alignas 190000
////#endif
////#if !defined(__cpp_default_function_template_args)
////#define __cpp_default_function_template_args 190000
////#endif
////#if !defined(__cpp_defaulted_functions)
////#define __cpp_defaulted_functions 190000
////#endif
////#if !defined(__cpp_deleted_functions)
////#define __cpp_deleted_functions 190000
////#endif
////#if !defined(__cpp_generalized_initializers)
////#define __cpp_generalized_initializers 190000
////#endif
////#if !defined(__cpp_implicit_moves)
////#define __cpp_implicit_moves 190000
////#endif
////#if !defined(__cpp_inline_namespaces)
////#define __cpp_inline_namespaces 190000
////#endif
////#if !defined(__cpp_local_type_template_args)
////#define __cpp_local_type_template_args 190000
////#endif
////#if !defined(__cpp_noexcept)
////#define __cpp_noexcept 190000
////#endif
////#if !defined(__cpp_nonstatic_member_init)
////#define __cpp_nonstatic_member_init 190000
////#endif
////#if !defined(__cpp_nullptr)
////#define __cpp_nullptr 190000
////#endif
////#if !defined(__cpp_override_control)
////#define __cpp_override_control 190000
////#endif
////#if !defined(__cpp_thread_local)
////#define __cpp_thread_local 190000
////#endif
////#if !defined(__cpp_auto_type)
////#define __cpp_auto_type 190000
////#endif
////#if !defined(__cpp_strong_enums)
////#define __cpp_strong_enums 190000
////#endif
////#if !defined(__cpp_trailing_return)
////#define __cpp_trailing_return 190000
////#endif
////#if !defined(__cpp_unrestricted_unions)
////#define __cpp_unrestricted_unions 190000
////#endif
#if !defined(__cpp_alias_templates)
#define __cpp_alias_templates 190000
#endif
#if !defined(__cpp_attributes)
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr)
#if __cplusplus >= 201402L
#define __cpp_constexpr 201304 // relaxed constexpr
#else
#define __cpp_constexpr 190000
#endif
#endif
#if !defined(__cpp_decltype)
#define __cpp_decltype 190000
#endif
#if !defined(__cpp_delegating_constructors)
#define __cpp_delegating_constructors 190000
#endif
#if !defined(__cpp_explicit_conversion) //// renamed from __cpp_explicit_conversions
#define __cpp_explicit_conversion 190000
#endif
#if !defined(__cpp_inheriting_constructors)
#define __cpp_inheriting_constructors 190000
#endif
#if !defined(__cpp_initializer_lists) //// NEW
#define __cpp_initializer_lists 190000
#endif
#if !defined(__cpp_lambdas)
#define __cpp_lambdas 190000
#endif
#if !defined(__cpp_nsdmi)
#define __cpp_nsdmi 190000 //// NEW
#endif
#if !defined(__cpp_range_based_for) //// renamed from __cpp_range_for
#define __cpp_range_based_for 190000
#endif
#if !defined(__cpp_raw_strings)
#define __cpp_raw_strings 190000
#endif
#if !defined(__cpp_ref_qualifiers) //// renamed from __cpp_reference_qualified_functions
#define __cpp_ref_qualifiers 190000
#endif
#if !defined(__cpp_rvalue_references)
#define __cpp_rvalue_references 190000
#endif
#if !defined(__cpp_static_assert)
#define __cpp_static_assert 190000
#endif
#if !defined(__cpp_unicode_characters) //// NEW
#define __cpp_unicode_characters 190000
#endif
#if !defined(__cpp_unicode_literals)
#define __cpp_unicode_literals 190000
#endif
#if !defined(__cpp_user_defined_literals)
#define __cpp_user_defined_literals 190000
#endif
#if !defined(__cpp_variadic_templates)
#define __cpp_variadic_templates 190000
#endif
#endif
#if __cplusplus >= 201402L
// Some of these macros ended up getting removed by ISO standards,
// they are prefixed with ////
////#if !defined(__cpp_contextual_conversions)
////#define __cpp_contextual_conversions 190000
////#endif
////#if !defined(__cpp_digit_separators)
////#define __cpp_digit_separators 190000
////#endif
////#if !defined(__cpp_relaxed_constexpr)
////#define __cpp_relaxed_constexpr 190000
////#endif
////#if !defined(__cpp_runtime_arrays)
////# define __cpp_runtime_arrays 190000
////#endif
#if !defined(__cpp_aggregate_nsdmi)
#define __cpp_aggregate_nsdmi 190000
#endif
#if !defined(__cpp_binary_literals)
#define __cpp_binary_literals 190000
#endif
#if !defined(__cpp_decltype_auto)
#define __cpp_decltype_auto 190000
#endif
#if !defined(__cpp_generic_lambdas)
#define __cpp_generic_lambdas 190000
#endif
#if !defined(__cpp_init_captures)
#define __cpp_init_captures 190000
#endif
#if !defined(__cpp_return_type_deduction)
#define __cpp_return_type_deduction 190000
#endif
#if !defined(__cpp_sized_deallocation)
#define __cpp_sized_deallocation 190000
#endif
#if !defined(__cpp_variable_templates)
#define __cpp_variable_templates 190000
#endif
#endif
// VS2010: _MSC_VER=1600
// VS2012: _MSC_VER=1700
// VS2013: _MSC_VER=1800
// VS2015: _MSC_VER=1900
// VS2017: _MSC_VER=1910
#if defined(_MSC_VER) && !defined(__clang__)
#if !defined(__cpp_exceptions) && defined(_CPPUNWIND)
#define __cpp_exceptions 190000
#endif
#if !defined(__cpp_rtti) && defined(_CPPRTTI)
#define __cpp_rtti 190000
#endif
// C++ 11
#if !defined(__cpp_alias_templates) && _MSC_VER >= 1800
#define __cpp_alias_templates 190000
#endif
#if !defined(__cpp_attributes)
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr) && _MSC_FULL_VER >= 190023506 /* VS2015 */
#define __cpp_constexpr 190000
#endif
#if !defined(__cpp_decltype) && _MSC_VER >= 1600
#define __cpp_decltype 190000
#endif
#if !defined(__cpp_delegating_constructors) && _MSC_VER >= 1800
#define __cpp_delegating_constructors 190000
#endif
#if !defined(__cpp_explicit_conversion) && _MSC_VER >= 1800
#define __cpp_explicit_conversion 190000
#endif
#if !defined(__cpp_inheriting_constructors) && _MSC_VER >= 1900
#define __cpp_inheriting_constructors 190000
#endif
#if !defined(__cpp_initializer_lists) && _MSC_VER >= 1900
#define __cpp_initializer_lists 190000
#endif
#if !defined(__cpp_lambdas) && _MSC_VER >= 1600
#define __cpp_lambdas 190000
#endif
#if !defined(__cpp_nsdmi) && _MSC_VER >= 1900
#define __cpp_nsdmi 190000
#endif
#if !defined(__cpp_range_based_for) && _MSC_VER >= 1700
#define __cpp_range_based_for 190000
#endif
#if !defined(__cpp_raw_strings) && _MSC_VER >= 1800
#define __cpp_raw_strings 190000
#endif
#if !defined(__cpp_ref_qualifiers) && _MSC_VER >= 1900
#define __cpp_ref_qualifiers 190000
#endif
#if !defined(__cpp_rvalue_references) && _MSC_VER >= 1600
#define __cpp_rvalue_references 190000
#endif
#if !defined(__cpp_static_assert) && _MSC_VER >= 1600
#define __cpp_static_assert 190000
#endif
//#if !defined(__cpp_unicode_literals)
//# define __cpp_unicode_literals 190000
//#endif
#if !defined(__cpp_user_defined_literals) && _MSC_VER >= 1900
#define __cpp_user_defined_literals 190000
#endif
#if !defined(__cpp_variadic_templates) && _MSC_VER >= 1800
#define __cpp_variadic_templates 190000
#endif
// C++ 14
//#if !defined(__cpp_aggregate_nsdmi)
//#define __cpp_aggregate_nsdmi 190000
//#endif
#if !defined(__cpp_binary_literals) && _MSC_VER >= 1900
#define __cpp_binary_literals 190000
#endif
#if !defined(__cpp_decltype_auto) && _MSC_VER >= 1900
#define __cpp_decltype_auto 190000
#endif
#if !defined(__cpp_generic_lambdas) && _MSC_VER >= 1900
#define __cpp_generic_lambdas 190000
#endif
#if !defined(__cpp_init_captures) && _MSC_VER >= 1900
#define __cpp_init_captures 190000
#endif
#if !defined(__cpp_return_type_deduction) && _MSC_VER >= 1900
#define __cpp_return_type_deduction 190000
#endif
#if !defined(__cpp_sized_deallocation) && _MSC_VER >= 1900
#define __cpp_sized_deallocation 190000
#endif
#if !defined(__cpp_variable_templates) && _MSC_FULL_VER >= 190023506
#define __cpp_variable_templates 190000
#endif
#endif // _MSC_VER
// Much to my surprise, GCC's support of these is actually incomplete, so fill in the gaps
#if (defined(__GNUC__) && !defined(__clang__))
#define QUICKCPPLIB_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if !defined(__cpp_exceptions) && defined(__EXCEPTIONS)
#define __cpp_exceptions 190000
#endif
#if !defined(__cpp_rtti) && defined(__GXX_RTTI)
#define __cpp_rtti 190000
#endif
// C++ 11
#if defined(__GXX_EXPERIMENTAL_CXX0X__)
#if !defined(__cpp_alias_templates) && (QUICKCPPLIB_GCC >= 40700)
#define __cpp_alias_templates 190000
#endif
#if !defined(__cpp_attributes) && (QUICKCPPLIB_GCC >= 40800)
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr) && (QUICKCPPLIB_GCC >= 40600)
#define __cpp_constexpr 190000
#endif
#if !defined(__cpp_decltype) && (QUICKCPPLIB_GCC >= 40300)
#define __cpp_decltype 190000
#endif
#if !defined(__cpp_delegating_constructors) && (QUICKCPPLIB_GCC >= 40700)
#define __cpp_delegating_constructors 190000
#endif
#if !defined(__cpp_explicit_conversion) && (QUICKCPPLIB_GCC >= 40500)
#define __cpp_explicit_conversion 190000
#endif
#if !defined(__cpp_inheriting_constructors) && (QUICKCPPLIB_GCC >= 40800)
#define __cpp_inheriting_constructors 190000
#endif
#if !defined(__cpp_initializer_lists) && (QUICKCPPLIB_GCC >= 40800)
#define __cpp_initializer_lists 190000
#endif
#if !defined(__cpp_lambdas) && (QUICKCPPLIB_GCC >= 40500)
#define __cpp_lambdas 190000
#endif
#if !defined(__cpp_nsdmi) && (QUICKCPPLIB_GCC >= 40700)
#define __cpp_nsdmi 190000
#endif
#if !defined(__cpp_range_based_for) && (QUICKCPPLIB_GCC >= 40600)
#define __cpp_range_based_for 190000
#endif
#if !defined(__cpp_raw_strings) && (QUICKCPPLIB_GCC >= 40500)
#define __cpp_raw_strings 190000
#endif
#if !defined(__cpp_ref_qualifiers) && (QUICKCPPLIB_GCC >= 40801)
#define __cpp_ref_qualifiers 190000
#endif
// __cpp_rvalue_reference deviation
#if !defined(__cpp_rvalue_references) && defined(__cpp_rvalue_reference)
#define __cpp_rvalue_references __cpp_rvalue_reference
#endif
#if !defined(__cpp_static_assert) && (QUICKCPPLIB_GCC >= 40300)
#define __cpp_static_assert 190000
#endif
#if !defined(__cpp_unicode_characters) && (QUICKCPPLIB_GCC >= 40500)
#define __cpp_unicode_characters 190000
#endif
#if !defined(__cpp_unicode_literals) && (QUICKCPPLIB_GCC >= 40500)
#define __cpp_unicode_literals 190000
#endif
#if !defined(__cpp_user_defined_literals) && (QUICKCPPLIB_GCC >= 40700)
#define __cpp_user_defined_literals 190000
#endif
#if !defined(__cpp_variadic_templates) && (QUICKCPPLIB_GCC >= 40400)
#define __cpp_variadic_templates 190000
#endif
// C++ 14
// Every C++ 14 supporting GCC does the right thing here
#endif // __GXX_EXPERIMENTAL_CXX0X__
#endif // GCC
// clang deviates in some places from the present SG-10 draft, plus older
// clangs are quite incomplete
#if defined(__clang__)
#define QUICKCPPLIB_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#if !defined(__cpp_exceptions) && (defined(__EXCEPTIONS) || defined(_CPPUNWIND))
#define __cpp_exceptions 190000
#endif
#if !defined(__cpp_rtti) && (defined(__GXX_RTTI) || defined(_CPPRTTI))
#define __cpp_rtti 190000
#endif
// C++ 11
#if defined(__GXX_EXPERIMENTAL_CXX0X__)
#if !defined(__cpp_alias_templates) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_alias_templates 190000
#endif
#if !defined(__cpp_attributes) && (QUICKCPPLIB_CLANG >= 30300)
#define __cpp_attributes 190000
#endif
#if !defined(__cpp_constexpr) && (QUICKCPPLIB_CLANG >= 30100)
#define __cpp_constexpr 190000
#endif
#if !defined(__cpp_decltype) && (QUICKCPPLIB_CLANG >= 20900)
#define __cpp_decltype 190000
#endif
#if !defined(__cpp_delegating_constructors) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_delegating_constructors 190000
#endif
#if !defined(__cpp_explicit_conversion) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_explicit_conversion 190000
#endif
#if !defined(__cpp_inheriting_constructors) && (QUICKCPPLIB_CLANG >= 30300)
#define __cpp_inheriting_constructors 190000
#endif
#if !defined(__cpp_initializer_lists) && (QUICKCPPLIB_CLANG >= 30100)
#define __cpp_initializer_lists 190000
#endif
#if !defined(__cpp_lambdas) && (QUICKCPPLIB_CLANG >= 30100)
#define __cpp_lambdas 190000
#endif
#if !defined(__cpp_nsdmi) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_nsdmi 190000
#endif
#if !defined(__cpp_range_based_for) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_range_based_for 190000
#endif
// __cpp_raw_string_literals deviation
#if !defined(__cpp_raw_strings) && defined(__cpp_raw_string_literals)
#define __cpp_raw_strings __cpp_raw_string_literals
#endif
#if !defined(__cpp_raw_strings) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_raw_strings 190000
#endif
#if !defined(__cpp_ref_qualifiers) && (QUICKCPPLIB_CLANG >= 20900)
#define __cpp_ref_qualifiers 190000
#endif
// __cpp_rvalue_reference deviation
#if !defined(__cpp_rvalue_references) && defined(__cpp_rvalue_reference)
#define __cpp_rvalue_references __cpp_rvalue_reference
#endif
#if !defined(__cpp_rvalue_references) && (QUICKCPPLIB_CLANG >= 20900)
#define __cpp_rvalue_references 190000
#endif
#if !defined(__cpp_static_assert) && (QUICKCPPLIB_CLANG >= 20900)
#define __cpp_static_assert 190000
#endif
#if !defined(__cpp_unicode_characters) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_unicode_characters 190000
#endif
#if !defined(__cpp_unicode_literals) && (QUICKCPPLIB_CLANG >= 30000)
#define __cpp_unicode_literals 190000
#endif
// __cpp_user_literals deviation
#if !defined(__cpp_user_defined_literals) && defined(__cpp_user_literals)
#define __cpp_user_defined_literals __cpp_user_literals
#endif
#if !defined(__cpp_user_defined_literals) && (QUICKCPPLIB_CLANG >= 30100)
#define __cpp_user_defined_literals 190000
#endif
#if !defined(__cpp_variadic_templates) && (QUICKCPPLIB_CLANG >= 20900)
#define __cpp_variadic_templates 190000
#endif
// C++ 14
// Every C++ 14 supporting clang does the right thing here
#endif // __GXX_EXPERIMENTAL_CXX0X__
#endif // clang
#endif
#ifndef QUICKCPPLIB_DISABLE_ABI_PERMUTATION
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define QUICKCPPLIB_PREVIOUS_COMMIT_REF 9a151aab3abaf1ced6b0b82f9328beb536386254
#define QUICKCPPLIB_PREVIOUS_COMMIT_DATE "2021-02-23 11:25:30 +00:00"
#define QUICKCPPLIB_PREVIOUS_COMMIT_UNIQUE 9a151aab
#endif
#define QUICKCPPLIB_VERSION_GLUE2(a, b) a##b
#define QUICKCPPLIB_VERSION_GLUE(a, b) QUICKCPPLIB_VERSION_GLUE2(a, b)
// clang-format off
#if defined(QUICKCPPLIB_DISABLE_ABI_PERMUTATION)
#define QUICKCPPLIB_NAMESPACE quickcpplib
#define QUICKCPPLIB_NAMESPACE_BEGIN namespace quickcpplib {
#define QUICKCPPLIB_NAMESPACE_END }
#else
#define QUICKCPPLIB_NAMESPACE quickcpplib::QUICKCPPLIB_VERSION_GLUE(_, QUICKCPPLIB_PREVIOUS_COMMIT_UNIQUE)
#define QUICKCPPLIB_NAMESPACE_BEGIN namespace quickcpplib { namespace QUICKCPPLIB_VERSION_GLUE(_, QUICKCPPLIB_PREVIOUS_COMMIT_UNIQUE) {
#define QUICKCPPLIB_NAMESPACE_END } }
#endif
// clang-format on
#ifdef _MSC_VER
#define QUICKCPPLIB_BIND_MESSAGE_PRAGMA2(x) __pragma(message(x))
#define QUICKCPPLIB_BIND_MESSAGE_PRAGMA(x) QUICKCPPLIB_BIND_MESSAGE_PRAGMA2(x)
#define QUICKCPPLIB_BIND_MESSAGE_PREFIX(type) __FILE__ "(" QUICKCPPLIB_BIND_STRINGIZE2(__LINE__) "): " type ": "
#define QUICKCPPLIB_BIND_MESSAGE_(type, prefix, msg) QUICKCPPLIB_BIND_MESSAGE_PRAGMA(prefix msg)
#else
#define QUICKCPPLIB_BIND_MESSAGE_PRAGMA2(x) _Pragma(#x)
#define QUICKCPPLIB_BIND_MESSAGE_PRAGMA(type, x) QUICKCPPLIB_BIND_MESSAGE_PRAGMA2(type x)
#define QUICKCPPLIB_BIND_MESSAGE_(type, prefix, msg) QUICKCPPLIB_BIND_MESSAGE_PRAGMA(type, msg)
#endif
//! Have the compiler output a message
#define QUICKCPPLIB_MESSAGE(msg) QUICKCPPLIB_BIND_MESSAGE_(message, QUICKCPPLIB_BIND_MESSAGE_PREFIX("message"), msg)
//! Have the compiler output a note
#define QUICKCPPLIB_NOTE(msg) QUICKCPPLIB_BIND_MESSAGE_(message, QUICKCPPLIB_BIND_MESSAGE_PREFIX("note"), msg)
//! Have the compiler output a warning
#define QUICKCPPLIB_WARNING(msg) QUICKCPPLIB_BIND_MESSAGE_(GCC warning, QUICKCPPLIB_BIND_MESSAGE_PREFIX("warning"), msg)
//! Have the compiler output an error
#define QUICKCPPLIB_ERROR(msg) QUICKCPPLIB_BIND_MESSAGE_(GCC error, QUICKCPPLIB_BIND_MESSAGE_PREFIX("error"), msg)
#define QUICKCPPLIB_ANNOTATE_RWLOCK_CREATE(p)
#define QUICKCPPLIB_ANNOTATE_RWLOCK_DESTROY(p)
#define QUICKCPPLIB_ANNOTATE_RWLOCK_ACQUIRED(p, s)
#define QUICKCPPLIB_ANNOTATE_RWLOCK_RELEASED(p, s)
#define QUICKCPPLIB_ANNOTATE_IGNORE_READS_BEGIN()
#define QUICKCPPLIB_ANNOTATE_IGNORE_READS_END()
#define QUICKCPPLIB_ANNOTATE_IGNORE_WRITES_BEGIN()
#define QUICKCPPLIB_ANNOTATE_IGNORE_WRITES_END()
#define QUICKCPPLIB_DRD_IGNORE_VAR(x)
#define QUICKCPPLIB_DRD_STOP_IGNORING_VAR(x)
#define QUICKCPPLIB_RUNNING_ON_VALGRIND (0)
#ifndef QUICKCPPLIB_IN_THREAD_SANITIZER
#if defined(__has_feature)
#if __has_feature(thread_sanitizer)
#define QUICKCPPLIB_IN_THREAD_SANITIZER 1
#endif
#elif defined(__SANITIZE_THREAD__)
#define QUICKCPPLIB_IN_THREAD_SANITIZER 1
#endif
#endif
#ifndef QUICKCPPLIB_IN_THREAD_SANITIZER
#define QUICKCPPLIB_IN_THREAD_SANITIZER 0
#endif
#if QUICKCPPLIB_IN_THREAD_SANITIZER
#define QUICKCPPLIB_DISABLE_THREAD_SANITIZE __attribute__((no_sanitize_thread))
#else
#define QUICKCPPLIB_DISABLE_THREAD_SANITIZE
#endif
#ifndef QUICKCPPLIB_SMT_PAUSE
#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER >= 1310 && (defined(_M_IX86) || defined(_M_X64))
extern "C" void _mm_pause();
#pragma intrinsic(_mm_pause)
#define QUICKCPPLIB_SMT_PAUSE _mm_pause();
#elif !defined(__c2__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#define QUICKCPPLIB_SMT_PAUSE __asm__ __volatile__("rep; nop" : : : "memory");
#endif
#endif
#ifndef QUICKCPPLIB_FORCEINLINE
#if defined(_MSC_VER)
#define QUICKCPPLIB_FORCEINLINE __forceinline
#elif defined(__GNUC__)
#define QUICKCPPLIB_FORCEINLINE __attribute__((always_inline))
#else
#define QUICKCPPLIB_FORCEINLINE
#endif
#endif
#ifndef QUICKCPPLIB_NOINLINE
#if defined(_MSC_VER)
#define QUICKCPPLIB_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
#define QUICKCPPLIB_NOINLINE __attribute__((noinline))
#else
#define QUICKCPPLIB_NOINLINE
#endif
#endif
#ifdef __has_cpp_attribute
#define QUICKCPPLIB_HAS_CPP_ATTRIBUTE(attr) __has_cpp_attribute(attr)
#else
#define QUICKCPPLIB_HAS_CPP_ATTRIBUTE(attr) (0)
#endif
#if !defined(QUICKCPPLIB_NORETURN)
#if QUICKCPPLIB_HAS_CPP_ATTRIBUTE(noreturn)
#define QUICKCPPLIB_NORETURN [[noreturn]]
#elif defined(_MSC_VER)
#define QUICKCPPLIB_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
#define QUICKCPPLIB_NORETURN __attribute__((__noreturn__))
#else
#define QUICKCPPLIB_NORETURN
#endif
#endif
#ifndef QUICKCPPLIB_NODISCARD
#if 0L || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#define QUICKCPPLIB_NODISCARD [[nodiscard]]
#endif
#endif
#ifndef QUICKCPPLIB_NODISCARD
#if QUICKCPPLIB_HAS_CPP_ATTRIBUTE(nodiscard)
#define QUICKCPPLIB_NODISCARD [[nodiscard]]
#elif defined(__clang__) // deliberately not GCC
#define QUICKCPPLIB_NODISCARD __attribute__((warn_unused_result))
#elif defined(_MSC_VER)
// _Must_inspect_result_ expands into this
#define QUICKCPPLIB_NODISCARD __declspec("SAL_name" "(" "\"_Must_inspect_result_\"" "," "\"\"" "," "\"2\"" ")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
#endif
#endif
#ifndef QUICKCPPLIB_NODISCARD
#define QUICKCPPLIB_NODISCARD
#endif
#ifndef QUICKCPPLIB_SYMBOL_VISIBLE
#if defined(_MSC_VER)
#define QUICKCPPLIB_SYMBOL_VISIBLE
#elif defined(__GNUC__)
#define QUICKCPPLIB_SYMBOL_VISIBLE __attribute__((visibility("default")))
#else
#define QUICKCPPLIB_SYMBOL_VISIBLE
#endif
#endif
#ifndef QUICKCPPLIB_SYMBOL_EXPORT
#if defined(_MSC_VER)
#define QUICKCPPLIB_SYMBOL_EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define QUICKCPPLIB_SYMBOL_EXPORT __attribute__((visibility("default")))
#else
#define QUICKCPPLIB_SYMBOL_EXPORT
#endif
#endif
#ifndef QUICKCPPLIB_SYMBOL_IMPORT
#if defined(_MSC_VER)
#define QUICKCPPLIB_SYMBOL_IMPORT __declspec(dllimport)
#elif defined(__GNUC__)
#define QUICKCPPLIB_SYMBOL_IMPORT
#else
#define QUICKCPPLIB_SYMBOL_IMPORT
#endif
#endif
#ifndef QUICKCPPLIB_THREAD_LOCAL
#if _MSC_VER >= 1800
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif __cplusplus >= 201103L
#if __GNUC__ >= 5 && !defined(__clang__)
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#elif defined(__has_feature)
#if __has_feature(cxx_thread_local)
#define QUICKCPPLIB_THREAD_LOCAL_IS_CXX11 1
#endif
#endif
#endif
#ifdef QUICKCPPLIB_THREAD_LOCAL_IS_CXX11
#define QUICKCPPLIB_THREAD_LOCAL thread_local
#endif
#ifndef QUICKCPPLIB_THREAD_LOCAL
#if defined(_MSC_VER)
#define QUICKCPPLIB_THREAD_LOCAL __declspec(thread)
#elif defined(__GNUC__)
#define QUICKCPPLIB_THREAD_LOCAL __thread
#else
#error Unknown compiler, cannot set QUICKCPPLIB_THREAD_LOCAL
#endif
#endif
#endif
/* MSVC capable preprocessor macro overloading
(C) 2014-2017 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
File Created: Aug 2014
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef QUICKCPPLIB_PREPROCESSOR_MACRO_OVERLOAD_H
#define QUICKCPPLIB_PREPROCESSOR_MACRO_OVERLOAD_H
#define QUICKCPPLIB_GLUE(x, y) x y
#define QUICKCPPLIB_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
#define QUICKCPPLIB_EXPAND_ARGS(args) QUICKCPPLIB_RETURN_ARG_COUNT args
#define QUICKCPPLIB_COUNT_ARGS_MAX8(...) QUICKCPPLIB_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define QUICKCPPLIB_OVERLOAD_MACRO2(name, count) name##count
#define QUICKCPPLIB_OVERLOAD_MACRO1(name, count) QUICKCPPLIB_OVERLOAD_MACRO2(name, count)
#define QUICKCPPLIB_OVERLOAD_MACRO(name, count) QUICKCPPLIB_OVERLOAD_MACRO1(name, count)
#define QUICKCPPLIB_CALL_OVERLOAD(name, ...) QUICKCPPLIB_GLUE(QUICKCPPLIB_OVERLOAD_MACRO(name, QUICKCPPLIB_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
#define QUICKCPPLIB_GLUE_(x, y) x y
#define QUICKCPPLIB_RETURN_ARG_COUNT_(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
#define QUICKCPPLIB_EXPAND_ARGS_(args) QUICKCPPLIB_RETURN_ARG_COUNT_ args
#define QUICKCPPLIB_COUNT_ARGS_MAX8_(...) QUICKCPPLIB_EXPAND_ARGS_((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define QUICKCPPLIB_OVERLOAD_MACRO2_(name, count) name##count
#define QUICKCPPLIB_OVERLOAD_MACRO1_(name, count) QUICKCPPLIB_OVERLOAD_MACRO2_(name, count)
#define QUICKCPPLIB_OVERLOAD_MACRO_(name, count) QUICKCPPLIB_OVERLOAD_MACRO1_(name, count)
#define QUICKCPPLIB_CALL_OVERLOAD_(name, ...) QUICKCPPLIB_GLUE_(QUICKCPPLIB_OVERLOAD_MACRO_(name, QUICKCPPLIB_COUNT_ARGS_MAX8_(__VA_ARGS__)), (__VA_ARGS__))
#endif
#if defined(__cpp_concepts) && !defined(QUICKCPPLIB_DISABLE_CONCEPTS_SUPPORT)
#define QUICKCPPLIB_TREQUIRES_EXPAND8(a, b, c, d, e, f, g, h) a &&QUICKCPPLIB_TREQUIRES_EXPAND7(b, c, d, e, f, g, h)
#define QUICKCPPLIB_TREQUIRES_EXPAND7(a, b, c, d, e, f, g) a &&QUICKCPPLIB_TREQUIRES_EXPAND6(b, c, d, e, f, g)
#define QUICKCPPLIB_TREQUIRES_EXPAND6(a, b, c, d, e, f) a &&QUICKCPPLIB_TREQUIRES_EXPAND5(b, c, d, e, f)
#define QUICKCPPLIB_TREQUIRES_EXPAND5(a, b, c, d, e) a &&QUICKCPPLIB_TREQUIRES_EXPAND4(b, c, d, e)
#define QUICKCPPLIB_TREQUIRES_EXPAND4(a, b, c, d) a &&QUICKCPPLIB_TREQUIRES_EXPAND3(b, c, d)
#define QUICKCPPLIB_TREQUIRES_EXPAND3(a, b, c) a &&QUICKCPPLIB_TREQUIRES_EXPAND2(b, c)
#define QUICKCPPLIB_TREQUIRES_EXPAND2(a, b) a &&QUICKCPPLIB_TREQUIRES_EXPAND1(b)
#define QUICKCPPLIB_TREQUIRES_EXPAND1(a) a
//! Expands into a && b && c && ...
#define QUICKCPPLIB_TREQUIRES(...) requires QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_TREQUIRES_EXPAND, __VA_ARGS__)
#define QUICKCPPLIB_TEMPLATE(...) template <__VA_ARGS__>
#define QUICKCPPLIB_TEXPR(...) requires { (__VA_ARGS__); }
#define QUICKCPPLIB_TPRED(...) (__VA_ARGS__)
#if !defined(_MSC_VER) || _MSC_FULL_VER >= 192400000 // VS 2019 16.3 is broken here
#define QUICKCPPLIB_REQUIRES(...) requires(__VA_ARGS__)
#else
#define QUICKCPPLIB_REQUIRES(...)
#endif
#else
#define QUICKCPPLIB_TEMPLATE(...) template <__VA_ARGS__
#define QUICKCPPLIB_TREQUIRES(...) , __VA_ARGS__ >
#define QUICKCPPLIB_TEXPR(...) typename = decltype(__VA_ARGS__)
#ifdef _MSC_VER
// MSVC gives an error if every specialisation of a template is always ill-formed, so
// the more powerful SFINAE form below causes pukeage :(
#define QUICKCPPLIB_TPRED(...) typename = typename std::enable_if<(__VA_ARGS__)>::type
#else
#define QUICKCPPLIB_TPRED(...) typename std::enable_if<(__VA_ARGS__), bool>::type = true
#endif
#define QUICKCPPLIB_REQUIRES(...)
#endif
#endif
#ifndef __cpp_variadic_templates
#error Outcome needs variadic template support in the compiler
#endif
#if __cpp_constexpr < 201304 && _MSC_FULL_VER < 191100000
#error Outcome needs constexpr (C++ 14) support in the compiler
#endif
#ifndef __cpp_variable_templates
#error Outcome needs variable template support in the compiler
#endif
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 6
#error Due to a bug in nested template variables parsing, Outcome does not work on GCCs earlier than v6.
#endif
#ifndef OUTCOME_SYMBOL_VISIBLE
#define OUTCOME_SYMBOL_VISIBLE QUICKCPPLIB_SYMBOL_VISIBLE
#endif
#ifndef OUTCOME_FORCEINLINE
#define OUTCOME_FORCEINLINE QUICKCPPLIB_FORCEINLINE
#endif
#ifndef OUTCOME_NODISCARD
#define OUTCOME_NODISCARD QUICKCPPLIB_NODISCARD
#endif
#ifndef OUTCOME_THREAD_LOCAL
#define OUTCOME_THREAD_LOCAL QUICKCPPLIB_THREAD_LOCAL
#endif
#ifndef OUTCOME_TEMPLATE
#define OUTCOME_TEMPLATE(...) QUICKCPPLIB_TEMPLATE(__VA_ARGS__)
#endif
#ifndef OUTCOME_TREQUIRES
#define OUTCOME_TREQUIRES(...) QUICKCPPLIB_TREQUIRES(__VA_ARGS__)
#endif
#ifndef OUTCOME_TEXPR
#define OUTCOME_TEXPR(...) QUICKCPPLIB_TEXPR(__VA_ARGS__)
#endif
#ifndef OUTCOME_TPRED
#define OUTCOME_TPRED(...) QUICKCPPLIB_TPRED(__VA_ARGS__)
#endif
#ifndef OUTCOME_REQUIRES
#define OUTCOME_REQUIRES(...) QUICKCPPLIB_REQUIRES(__VA_ARGS__)
#endif
/* Convenience macros for importing local namespace binds
(C) 2014-2017 Niall Douglas <http://www.nedproductions.biz/> (9 commits)
File Created: Aug 2014
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef QUICKCPPLIB_BIND_IMPORT_HPP
#define QUICKCPPLIB_BIND_IMPORT_HPP
/* 2014-10-9 ned: I lost today figuring out the below. I really hate the C preprocessor now.
*
* Anyway, infinity = 8. It's easy to expand below if needed.
*/
#define QUICKCPPLIB_BIND_STRINGIZE(a) #a
#define QUICKCPPLIB_BIND_STRINGIZE2(a) QUICKCPPLIB_BIND_STRINGIZE(a)
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION8(a, b, c, d, e, f, g, h) a##_##b##_##c##_##d##_##e##_##f##_##g##_##h
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION7(a, b, c, d, e, f, g) a##_##b##_##c##_##d##_##e##_##f##_##g
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION6(a, b, c, d, e, f) a##_##b##_##c##_##d##_##e##_##f
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION5(a, b, c, d, e) a##_##b##_##c##_##d##_##e
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION4(a, b, c, d) a##_##b##_##c##_##d
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION3(a, b, c) a##_##b##_##c
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION2(a, b) a##_##b
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION1(a) a
//! Concatenates each parameter with _
#define QUICKCPPLIB_BIND_NAMESPACE_VERSION(...) QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_BIND_NAMESPACE_VERSION, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT_2(name, modifier) name
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT2(name, modifier) ::name
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT_1(name) name
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT1(name) ::name
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT_(...) QUICKCPPLIB_CALL_OVERLOAD_(QUICKCPPLIB_BIND_NAMESPACE_SELECT_, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_SELECT(...) QUICKCPPLIB_CALL_OVERLOAD_(QUICKCPPLIB_BIND_NAMESPACE_SELECT, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND8(a, b, c, d, e, f, g, h) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c QUICKCPPLIB_BIND_NAMESPACE_SELECT d QUICKCPPLIB_BIND_NAMESPACE_SELECT e QUICKCPPLIB_BIND_NAMESPACE_SELECT f QUICKCPPLIB_BIND_NAMESPACE_SELECT g QUICKCPPLIB_BIND_NAMESPACE_SELECT h
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND7(a, b, c, d, e, f, g) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c QUICKCPPLIB_BIND_NAMESPACE_SELECT d QUICKCPPLIB_BIND_NAMESPACE_SELECT e QUICKCPPLIB_BIND_NAMESPACE_SELECT f QUICKCPPLIB_BIND_NAMESPACE_SELECT g
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND6(a, b, c, d, e, f) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c QUICKCPPLIB_BIND_NAMESPACE_SELECT d QUICKCPPLIB_BIND_NAMESPACE_SELECT e QUICKCPPLIB_BIND_NAMESPACE_SELECT f
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND5(a, b, c, d, e) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c QUICKCPPLIB_BIND_NAMESPACE_SELECT d QUICKCPPLIB_BIND_NAMESPACE_SELECT e
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND4(a, b, c, d) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c QUICKCPPLIB_BIND_NAMESPACE_SELECT d
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND3(a, b, c) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b QUICKCPPLIB_BIND_NAMESPACE_SELECT c
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND2(a, b) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a QUICKCPPLIB_BIND_NAMESPACE_SELECT b
#define QUICKCPPLIB_BIND_NAMESPACE_EXPAND1(a) QUICKCPPLIB_BIND_NAMESPACE_SELECT_ a
//! Expands into a::b::c:: ...
#define QUICKCPPLIB_BIND_NAMESPACE(...) QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_BIND_NAMESPACE_EXPAND, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT2(name, modifier) modifier namespace name {
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT1(name) namespace name {
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT(...) QUICKCPPLIB_CALL_OVERLOAD_(QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND8(a, b, c, d, e, f, g, h) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND7(b, c, d, e, f, g, h)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND7(a, b, c, d, e, f, g) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND6(b, c, d, e, f, g)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND6(a, b, c, d, e, f) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND5(b, c, d, e, f)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND5(a, b, c, d, e) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND4(b, c, d, e)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND4(a, b, c, d) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND3(b, c, d)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND3(a, b, c) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND2(b, c)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND2(a, b) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND1(b)
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND1(a) QUICKCPPLIB_BIND_NAMESPACE_BEGIN_NAMESPACE_SELECT a
//! Expands into namespace a { namespace b { namespace c ...
#define QUICKCPPLIB_BIND_NAMESPACE_BEGIN(...) QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_BIND_NAMESPACE_BEGIN_EXPAND, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT2(name, modifier) modifier namespace name {
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT1(name) export namespace name {
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT(...) QUICKCPPLIB_CALL_OVERLOAD_(QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND8(a, b, c, d, e, f, g, h) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND7(b, c, d, e, f, g, h)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND7(a, b, c, d, e, f, g) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND6(b, c, d, e, f, g)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND6(a, b, c, d, e, f) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND5(b, c, d, e, f)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND5(a, b, c, d, e) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND4(b, c, d, e)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND4(a, b, c, d) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND3(b, c, d)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND3(a, b, c) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND2(b, c)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND2(a, b) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND1(b)
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND1(a) QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_NAMESPACE_SELECT a
//! Expands into export namespace a { namespace b { namespace c ...
#define QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN(...) QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN_EXPAND, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT2(name, modifier) }
#define QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT1(name) }
#define QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT(...) QUICKCPPLIB_CALL_OVERLOAD_(QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT, __VA_ARGS__)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND8(a, b, c, d, e, f, g, h) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND7(b, c, d, e, f, g, h)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND7(a, b, c, d, e, f, g) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND6(b, c, d, e, f, g)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND6(a, b, c, d, e, f) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND5(b, c, d, e, f)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND5(a, b, c, d, e) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND4(b, c, d, e)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND4(a, b, c, d) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND3(b, c, d)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND3(a, b, c) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND2(b, c)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND2(a, b) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND1(b)
#define QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND1(a) QUICKCPPLIB_BIND_NAMESPACE_END_NAMESPACE_SELECT a
//! Expands into } } ...
#define QUICKCPPLIB_BIND_NAMESPACE_END(...) QUICKCPPLIB_CALL_OVERLOAD(QUICKCPPLIB_BIND_NAMESPACE_END_EXPAND, __VA_ARGS__)
//! Expands into a static const char string array used to mark BindLib compatible namespaces
#define QUICKCPPLIB_BIND_DECLARE(decl, desc) static const char *quickcpplib_out[] = {#decl, desc};
#endif
#ifndef OUTCOME_ENABLE_LEGACY_SUPPORT_FOR
#define OUTCOME_ENABLE_LEGACY_SUPPORT_FOR 220 // the v2.2 Outcome release
#endif
#if defined(OUTCOME_UNSTABLE_VERSION)
/* UPDATED BY SCRIPT
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (225 commits)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define OUTCOME_PREVIOUS_COMMIT_REF 35644f5cdeb90f6f29d80714a371098d311cbd47
#define OUTCOME_PREVIOUS_COMMIT_DATE "2021-02-26 10:38:25 +00:00"
#define OUTCOME_PREVIOUS_COMMIT_UNIQUE 35644f5c
#define OUTCOME_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2, OUTCOME_PREVIOUS_COMMIT_UNIQUE))
#ifdef _DEBUG
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2d, OUTCOME_PREVIOUS_COMMIT_UNIQUE)))
#else
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2, OUTCOME_PREVIOUS_COMMIT_UNIQUE)))
#endif
#else
#define OUTCOME_V2 (QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2))
#ifdef _DEBUG
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2d)))
#else
#define OUTCOME_V2_CXX_MODULE_NAME QUICKCPPLIB_BIND_NAMESPACE((QUICKCPPLIB_BIND_NAMESPACE_VERSION(outcome_v2)))
#endif
#endif
#if defined(GENERATING_OUTCOME_MODULE_INTERFACE)
#define OUTCOME_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_EXPORT_BEGIN(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(OUTCOME_V2)
#else
#define OUTCOME_V2_NAMESPACE QUICKCPPLIB_BIND_NAMESPACE(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_EXPORT_BEGIN QUICKCPPLIB_BIND_NAMESPACE_BEGIN(OUTCOME_V2)
#define OUTCOME_V2_NAMESPACE_END QUICKCPPLIB_BIND_NAMESPACE_END(OUTCOME_V2)
#endif
#include <cstdint> // for uint32_t etc
#include <initializer_list>
#include <iosfwd> // for future serialisation
#include <new> // for placement in moves etc
#include <type_traits>
#ifndef OUTCOME_USE_STD_IN_PLACE_TYPE
#if defined(_MSC_VER) && _HAS_CXX17
#define OUTCOME_USE_STD_IN_PLACE_TYPE 1 // MSVC always has std::in_place_type
#elif __cplusplus >= 201700
// libstdc++ before GCC 6 doesn't have it, despite claiming C++ 17 support
#ifdef __has_include
#if !__has_include(<variant>)
#define OUTCOME_USE_STD_IN_PLACE_TYPE 0 // must have it if <variant> is present
#endif
#endif
#ifndef OUTCOME_USE_STD_IN_PLACE_TYPE
#define OUTCOME_USE_STD_IN_PLACE_TYPE 1
#endif
#else
#define OUTCOME_USE_STD_IN_PLACE_TYPE 0
#endif
#endif
#if OUTCOME_USE_STD_IN_PLACE_TYPE
#include <utility> // for in_place_type_t
OUTCOME_V2_NAMESPACE_BEGIN
template <class T> using in_place_type_t = std::in_place_type_t<T>;
using std::in_place_type;
OUTCOME_V2_NAMESPACE_END
#else
OUTCOME_V2_NAMESPACE_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class T> in_place_type_t. Potential doc page: `in_place_type_t<T>`
*/
template <class T> struct in_place_type_t
{
explicit in_place_type_t() = default;
};
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> constexpr in_place_type_t<T> in_place_type{};
OUTCOME_V2_NAMESPACE_END
#endif
#ifndef OUTCOME_TRIVIAL_ABI
#if 0L || __clang_major__ >= 7
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
#define OUTCOME_TRIVIAL_ABI [[clang::trivial_abi]]
#else
#define OUTCOME_TRIVIAL_ABI
#endif
#endif
OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
// Test if type is an in_place_type_t
template <class T> struct is_in_place_type_t
{
static constexpr bool value = false;
};
template <class U> struct is_in_place_type_t<in_place_type_t<U>>
{
static constexpr bool value = true;
};
// Replace void with constructible void_type
struct empty_type
{
};
struct void_type
{
// We always compare true to another instance of me
constexpr bool operator==(void_type /*unused*/) const noexcept { return true; }
constexpr bool operator!=(void_type /*unused*/) const noexcept { return false; }
};
template <class T> using devoid = std::conditional_t<std::is_void<T>::value, void_type, T>;
template <class Output, class Input> using rebind_type5 = Output;
template <class Output, class Input>
using rebind_type4 = std::conditional_t< //
std::is_volatile<Input>::value, //
std::add_volatile_t<rebind_type5<Output, std::remove_volatile_t<Input>>>, //
rebind_type5<Output, Input>>;
template <class Output, class Input>
using rebind_type3 = std::conditional_t< //
std::is_const<Input>::value, //
std::add_const_t<rebind_type4<Output, std::remove_const_t<Input>>>, //
rebind_type4<Output, Input>>;
template <class Output, class Input>
using rebind_type2 = std::conditional_t< //
std::is_lvalue_reference<Input>::value, //
std::add_lvalue_reference_t<rebind_type3<Output, std::remove_reference_t<Input>>>, //
rebind_type3<Output, Input>>;
template <class Output, class Input>
using rebind_type = std::conditional_t< //
std::is_rvalue_reference<Input>::value, //
std::add_rvalue_reference_t<rebind_type2<Output, std::remove_reference_t<Input>>>, //
rebind_type2<Output, Input>>;
// static_assert(std::is_same_v<rebind_type<int, volatile const double &&>, volatile const int &&>, "");
/* True if type is the same or constructible. Works around a bug where clang + libstdc++
pukes on std::is_constructible<filesystem::path, void> (this bug is fixed upstream).
*/
template <class T, class U> struct _is_explicitly_constructible
{
static constexpr bool value = std::is_constructible<T, U>::value;
};
template <class T> struct _is_explicitly_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_explicitly_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class U> static constexpr bool is_explicitly_constructible = _is_explicitly_constructible<T, U>::value;
template <class T, class U> struct _is_implicitly_constructible
{
static constexpr bool value = std::is_convertible<U, T>::value;
};
template <class T> struct _is_implicitly_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_implicitly_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class U> static constexpr bool is_implicitly_constructible = _is_implicitly_constructible<T, U>::value;
template <class T, class... Args> struct _is_nothrow_constructible
{
static constexpr bool value = std::is_nothrow_constructible<T, Args...>::value;
};
template <class T> struct _is_nothrow_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_nothrow_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class... Args> static constexpr bool is_nothrow_constructible = _is_nothrow_constructible<T, Args...>::value;
template <class T, class... Args> struct _is_constructible
{
static constexpr bool value = std::is_constructible<T, Args...>::value;
};
template <class T> struct _is_constructible<T, void>
{
static constexpr bool value = false;
};
template <> struct _is_constructible<void, void>
{
static constexpr bool value = false;
};
template <class T, class... Args> static constexpr bool is_constructible = _is_constructible<T, Args...>::value;
#ifndef OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
#if defined(_MSC_VER) && _HAS_CXX17
#define OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 1 // MSVC always has std::is_nothrow_swappable
#elif __cplusplus >= 201700
// libstdc++ before GCC 6 doesn't have it, despite claiming C++ 17 support
#ifdef __has_include
#if !__has_include(<variant>)
#define OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 0
#endif
#endif
#ifndef OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
#define OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 1
#endif
#else
#define OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE 0
#endif
#endif
// True if type is nothrow swappable
#if !0L && OUTCOME_USE_STD_IS_NOTHROW_SWAPPABLE
template <class T> using is_nothrow_swappable = std::is_nothrow_swappable<T>;
#else
template <class T> struct is_nothrow_swappable
{
static constexpr bool value = std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value;
};
#endif
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#ifndef OUTCOME_THROW_EXCEPTION
#ifdef __cpp_exceptions
#define OUTCOME_THROW_EXCEPTION(expr) throw expr
#else
#ifdef __ANDROID__
#define OUTCOME_DISABLE_EXECINFO
#endif
#ifndef OUTCOME_DISABLE_EXECINFO
#ifdef _WIN32
/* Implements backtrace() et al from glibc on win64
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
File Created: Mar 2016
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BINDLIB_EXECINFO_WIN64_H
#define BOOST_BINDLIB_EXECINFO_WIN64_H
#ifndef _WIN32
#error Can only be included on Windows
#endif
#include <sal.h>
#include <stddef.h>
#ifdef QUICKCPPLIB_EXPORTS
#define EXECINFO_DECL extern __declspec(dllexport)
#else
#if defined(__cplusplus) && (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#define EXECINFO_DECL inline
#elif defined(QUICKCPPLIB_DYN_LINK) && !defined(QUICKCPPLIB_STATIC_LINK)
#define EXECINFO_DECL extern __declspec(dllimport)
#else
#define EXECINFO_DECL extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
//! Fill the array of void * at bt with up to len entries, returning entries filled.
EXECINFO_DECL _Check_return_ size_t backtrace(_Out_writes_(len) void **bt, _In_ size_t len);
//! Returns a malloced block of string representations of the input backtrace.
EXECINFO_DECL _Check_return_ _Ret_writes_maybenull_(len) char **backtrace_symbols(_In_reads_(len) void *const *bt, _In_ size_t len);
// extern void backtrace_symbols_fd(void *const *bt, size_t len, int fd);
#ifdef __cplusplus
}
#if (!defined(QUICKCPPLIB_HEADERS_ONLY) || QUICKCPPLIB_HEADERS_ONLY == 1) && !0L
#define QUICKCPPLIB_INCLUDED_BY_HEADER 1
/* Implements backtrace() et al from glibc on win64
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
File Created: Mar 2016
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
/* Implements backtrace() et al from glibc on win64
(C) 2016-2017 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
File Created: Mar 2016
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#include <atomic>
#include <stdlib.h> // for abort
#include <string.h>
// To avoid including windows.h, this source has been macro expanded and win32 function shimmed for C++ only
#if defined(__cplusplus) && !defined(__clang__)
namespace win32
{
extern _Ret_maybenull_ void *__stdcall LoadLibraryA(_In_ const char *lpLibFileName);
typedef int(__stdcall *GetProcAddress_returntype)();
extern GetProcAddress_returntype __stdcall GetProcAddress(_In_ void *hModule, _In_ const char *lpProcName);
extern _Success_(return != 0) unsigned short __stdcall RtlCaptureStackBackTrace(_In_ unsigned long FramesToSkip, _In_ unsigned long FramesToCapture,
_Out_writes_to_(FramesToCapture, return ) void **BackTrace,
_Out_opt_ unsigned long *BackTraceHash);
extern _Success_(return != 0)
_When_((cchWideChar == -1) && (cbMultiByte != 0),
_Post_equal_to_(_String_length_(lpMultiByteStr) +
1)) int __stdcall WideCharToMultiByte(_In_ unsigned int CodePage, _In_ unsigned long dwFlags, const wchar_t *lpWideCharStr,
_In_ int cchWideChar, _Out_writes_bytes_to_opt_(cbMultiByte, return ) char *lpMultiByteStr,
_In_ int cbMultiByte, _In_opt_ const char *lpDefaultChar, _Out_opt_ int *lpUsedDefaultChar);
#pragma comment(lib, "kernel32.lib")
#if (defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64))
#pragma comment(linker, "/alternatename:?LoadLibraryA@win32@@YAPEAXPEBD@Z=LoadLibraryA")
#pragma comment(linker, "/alternatename:?GetProcAddress@win32@@YAP6AHXZPEAXPEBD@Z=GetProcAddress")
#pragma comment(linker, "/alternatename:?RtlCaptureStackBackTrace@win32@@YAGKKPEAPEAXPEAK@Z=RtlCaptureStackBackTrace")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@@YAHIKPEB_WHPEADHPEBDPEAH@Z=WideCharToMultiByte")
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
#pragma comment(linker, "/alternatename:?LoadLibraryA@win32@@YGPAXPBD@Z=__imp__LoadLibraryA@4")
#pragma comment(linker, "/alternatename:?GetProcAddress@win32@@YGP6GHXZPAXPBD@Z=__imp__GetProcAddress@8")
#pragma comment(linker, "/alternatename:?RtlCaptureStackBackTrace@win32@@YGGKKPAPAXPAK@Z=__imp__RtlCaptureStackBackTrace@16")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@@YGHIKPB_WHPADHPBDPAH@Z=__imp__WideCharToMultiByte@32")
#elif defined(__arm__) || defined(_M_ARM)
#pragma comment(linker, "/alternatename:?LoadLibraryA@win32@@YAPAXPBD@Z=LoadLibraryA")
#pragma comment(linker, "/alternatename:?GetProcAddress@win32@@YAP6AHXZPAXPBD@Z=GetProcAddress")
#pragma comment(linker, "/alternatename:?RtlCaptureStackBackTrace@win32@@YAGKKPAPAXPAK@Z=RtlCaptureStackBackTrace")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@@YAHIKPB_WHPADHPBDPAH@Z=WideCharToMultiByte")
#else
#error Unknown architecture
#endif
} // namespace win32
#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <Windows.h>
#endif
#ifdef __cplusplus
namespace
{
#endif
typedef struct _IMAGEHLP_LINE64
{
unsigned long SizeOfStruct;
void *Key;
unsigned long LineNumber;
wchar_t *FileName;
unsigned long long int Address;
} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
typedef int(__stdcall *SymInitialize_t)(_In_ void *hProcess, _In_opt_ const wchar_t *UserSearchPath, _In_ int fInvadeProcess);
typedef int(__stdcall *SymGetLineFromAddr64_t)(_In_ void *hProcess, _In_ unsigned long long int dwAddr, _Out_ unsigned long *pdwDisplacement,
_Out_ PIMAGEHLP_LINE64 Line);
static std::atomic<unsigned> dbghelp_init_lock;
#if defined(__cplusplus) && !defined(__clang__)
static void *dbghelp;
#else
static HMODULE dbghelp;
#endif
static SymInitialize_t SymInitialize;
static SymGetLineFromAddr64_t SymGetLineFromAddr64;
static void load_dbghelp()
{
#if defined(__cplusplus) && !defined(__clang__)
using win32::GetProcAddress;
using win32::LoadLibraryA;
#endif
while(dbghelp_init_lock.exchange(1, std::memory_order_acq_rel))
;
if(dbghelp)
{
dbghelp_init_lock.store(0, std::memory_order_release);
return;
}
dbghelp = LoadLibraryA("DBGHELP.DLL");
if(dbghelp)
{
SymInitialize = (SymInitialize_t) GetProcAddress(dbghelp, "SymInitializeW");
if(!SymInitialize)
abort();
if(!SymInitialize((void *) (size_t) -1 /*GetCurrentProcess()*/, NULL, 1))
abort();
SymGetLineFromAddr64 = (SymGetLineFromAddr64_t) GetProcAddress(dbghelp, "SymGetLineFromAddrW64");
if(!SymGetLineFromAddr64)
abort();
}
dbghelp_init_lock.store(0, std::memory_order_release);
}
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C"
{
#endif
_Check_return_ size_t backtrace(_Out_writes_(len) void **bt, _In_ size_t len)
{
#if defined(__cplusplus) && !defined(__clang__)
using win32::RtlCaptureStackBackTrace;
#endif
return RtlCaptureStackBackTrace(1, (unsigned long) len, bt, NULL);
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 6385 6386) // MSVC static analyser can't grok this function. clang's analyser gives it thumbs up.
#endif
_Check_return_ _Ret_writes_maybenull_(len) char **backtrace_symbols(_In_reads_(len) void *const *bt, _In_ size_t len)
{
#if defined(__cplusplus) && !defined(__clang__)
using win32::WideCharToMultiByte;
#endif
size_t bytes = (len + 1) * sizeof(void *) + 256, n;
if(!len)
return NULL;
else
{
char **ret = (char **) malloc(bytes);
char *p = (char *) (ret + len + 1), *end = (char *) ret + bytes;
if(!ret)
return NULL;
for(n = 0; n < len + 1; n++)
ret[n] = NULL;
load_dbghelp();
for(n = 0; n < len; n++)
{
unsigned long displ;
IMAGEHLP_LINE64 ihl;
memset(&ihl, 0, sizeof(ihl));
ihl.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
int please_realloc = 0;
if(!bt[n])
{
ret[n] = NULL;
}
else
{
// Keep offset till later
ret[n] = (char *) ((char *) p - (char *) ret);
if(!SymGetLineFromAddr64 || !SymGetLineFromAddr64((void *) (size_t) -1 /*GetCurrentProcess()*/, (size_t) bt[n], &displ, &ihl))
{
if(n == 0)
{
free(ret);
return NULL;
}
ihl.FileName = (wchar_t *) L"unknown";
ihl.LineNumber = 0;
}
retry:
if(please_realloc)
{
char **temp = (char **) realloc(ret, bytes + 256);
if(!temp)
{
free(ret);
return NULL;
}
p = (char *) temp + (p - (char *) ret);
ret = temp;
bytes += 256;
end = (char *) ret + bytes;
}
if(ihl.FileName && ihl.FileName[0])
{
int plen = WideCharToMultiByte(65001 /*CP_UTF8*/, 0, ihl.FileName, -1, p, (int) (end - p), NULL, NULL);
if(!plen)
{
please_realloc = 1;
goto retry;
}
p[plen - 1] = 0;
p += plen - 1;
}
else
{
if(end - p < 16)
{
please_realloc = 1;
goto retry;
}
_ui64toa_s((size_t) bt[n], p, end - p, 16);
p = strchr(p, 0);
}
if(end - p < 16)
{
please_realloc = 1;
goto retry;
}
*p++ = ':';
_itoa_s(ihl.LineNumber, p, end - p, 10);
p = strchr(p, 0) + 1;
}
}
for(n = 0; n < len; n++)
{
if(ret[n])
ret[n] = (char *) ret + (size_t) ret[n];
}
return ret;
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// extern void backtrace_symbols_fd(void *const *bt, size_t len, int fd);
#ifdef __cplusplus
}
#endif
#undef QUICKCPPLIB_INCLUDED_BY_HEADER
#endif
#endif
#endif
#else
#include <execinfo.h>
#endif
#endif // OUTCOME_DISABLE_EXECINFO
#include <cstdio>
#include <cstdlib>
OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
QUICKCPPLIB_NORETURN inline void do_fatal_exit(const char *expr)
{
#if !defined(OUTCOME_DISABLE_EXECINFO)
void *bt[16];
size_t btlen = backtrace(bt, sizeof(bt) / sizeof(bt[0])); // NOLINT
#endif
fprintf(stderr, "FATAL: Outcome throws exception %s with exceptions disabled\n", expr); // NOLINT
#if !defined(OUTCOME_DISABLE_EXECINFO)
char **bts = backtrace_symbols(bt, btlen); // NOLINT
if(bts != nullptr)
{
for(size_t n = 0; n < btlen; n++)
{
fprintf(stderr, " %s\n", bts[n]); // NOLINT
}
free(bts); // NOLINT
}
#endif
abort();
}
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#define OUTCOME_THROW_EXCEPTION(expr) OUTCOME_V2_NAMESPACE::detail::do_fatal_exit(#expr), (void) (expr)
#endif
#endif
#ifndef BOOST_OUTCOME_AUTO_TEST_CASE
#define BOOST_OUTCOME_AUTO_TEST_CASE(a, b) BOOST_AUTO_TEST_CASE(a, b)
#endif
#endif
/* A very simple result type
(C) 2017-2021 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
File Created: June 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_RESULT_HPP
#define OUTCOME_BASIC_RESULT_HPP
/* Says how to convert value, error and exception types
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Nov 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_CONVERT_HPP
#define OUTCOME_CONVERT_HPP
/* Storage for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_RESULT_STORAGE_HPP
#define OUTCOME_BASIC_RESULT_STORAGE_HPP
/* Type sugar for success and failure
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (25 commits)
File Created: July 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_SUCCESS_FAILURE_HPP
#define OUTCOME_SUCCESS_FAILURE_HPP
OUTCOME_V2_NAMESPACE_BEGIN
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class T> success_type. Potential doc page: `success_type<T>`
*/
template <class T> struct OUTCOME_NODISCARD success_type
{
using value_type = T;
private:
value_type _value;
uint16_t _spare_storage{0};
public:
success_type() = default;
success_type(const success_type &) = default;
success_type(success_type &&) = default; // NOLINT
success_type &operator=(const success_type &) = default;
success_type &operator=(success_type &&) = default; // NOLINT
~success_type() = default;
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_same<success_type, std::decay_t<U>>::value))
constexpr explicit success_type(U &&v, uint16_t spare_storage = 0)
: _value(static_cast<U &&>(v)) // NOLINT
, _spare_storage(spare_storage)
{
}
constexpr value_type &value() & { return _value; }
constexpr const value_type &value() const & { return _value; }
constexpr value_type &&value() && { return static_cast<value_type &&>(_value); }
constexpr const value_type &&value() const && { return static_cast<value_type &&>(_value); }
constexpr uint16_t spare_storage() const { return _spare_storage; }
};
template <> struct OUTCOME_NODISCARD success_type<void>
{
using value_type = void;
constexpr uint16_t spare_storage() const { return 0; }
};
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state,
default constructing `T` if necessary.
*/
inline constexpr success_type<void> success() noexcept
{
return success_type<void>{};
}
/*! Returns type sugar for implicitly constructing a `basic_result<T>` with a successful state.
\effects Copies or moves the successful state supplied into the returned type sugar.
*/
template <class T> inline constexpr success_type<std::decay_t<T>> success(T &&v, uint16_t spare_storage = 0)
{
return success_type<std::decay_t<T>>{static_cast<T &&>(v), spare_storage};
}
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class EC, class E = void> failure_type. Potential doc page: `failure_type<EC, EP = void>`
*/
template <class EC, class E = void> struct OUTCOME_NODISCARD failure_type
{
using error_type = EC;
using exception_type = E;
private:
error_type _error;
exception_type _exception;
bool _have_error{false}, _have_exception{false};
uint16_t _spare_storage{0};
struct error_init_tag
{
};
struct exception_init_tag
{
};
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
failure_type &operator=(failure_type &&) = default; // NOLINT
~failure_type() = default;
template <class U, class V>
constexpr explicit failure_type(U &&u, V &&v, uint16_t spare_storage = 0)
: _error(static_cast<U &&>(u))
, _exception(static_cast<V &&>(v))
, _have_error(true)
, _have_exception(true)
, _spare_storage(spare_storage)
{
}
template <class U>
constexpr explicit failure_type(in_place_type_t<error_type> /*unused*/, U &&u, uint16_t spare_storage = 0, error_init_tag /*unused*/ = error_init_tag())
: _error(static_cast<U &&>(u))
, _exception()
, _have_error(true)
, _spare_storage(spare_storage)
{
}
template <class U>
constexpr explicit failure_type(in_place_type_t<exception_type> /*unused*/, U &&u, uint16_t spare_storage = 0,
exception_init_tag /*unused*/ = exception_init_tag())
: _error()
, _exception(static_cast<U &&>(u))
, _have_exception(true)
, _spare_storage(spare_storage)
{
}
constexpr bool has_error() const { return _have_error; }
constexpr bool has_exception() const { return _have_exception; }
constexpr error_type &error() & { return _error; }
constexpr const error_type &error() const & { return _error; }
constexpr error_type &&error() && { return static_cast<error_type &&>(_error); }
constexpr const error_type &&error() const && { return static_cast<error_type &&>(_error); }
constexpr exception_type &exception() & { return _exception; }
constexpr const exception_type &exception() const & { return _exception; }
constexpr exception_type &&exception() && { return static_cast<exception_type &&>(_exception); }
constexpr const exception_type &&exception() const && { return static_cast<exception_type &&>(_exception); }
constexpr uint16_t spare_storage() const { return _spare_storage; }
};
template <class EC> struct OUTCOME_NODISCARD failure_type<EC, void>
{
using error_type = EC;
using exception_type = void;
private:
error_type _error;
uint16_t _spare_storage{0};
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
failure_type &operator=(failure_type &&) = default; // NOLINT
~failure_type() = default;
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_same<failure_type, std::decay_t<U>>::value))
constexpr explicit failure_type(U &&u, uint16_t spare_storage = 0)
: _error(static_cast<U &&>(u)) // NOLINT
, _spare_storage(spare_storage)
{
}
constexpr error_type &error() & { return _error; }
constexpr const error_type &error() const & { return _error; }
constexpr error_type &&error() && { return static_cast<error_type &&>(_error); }
constexpr const error_type &&error() const && { return static_cast<error_type &&>(_error); }
constexpr uint16_t spare_storage() const { return _spare_storage; }
};
template <class E> struct OUTCOME_NODISCARD failure_type<void, E>
{
using error_type = void;
using exception_type = E;
private:
exception_type _exception;
uint16_t _spare_storage{0};
public:
failure_type() = default;
failure_type(const failure_type &) = default;
failure_type(failure_type &&) = default; // NOLINT
failure_type &operator=(const failure_type &) = default;
failure_type &operator=(failure_type &&) = default; // NOLINT
~failure_type() = default;
OUTCOME_TEMPLATE(class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_same<failure_type, std::decay_t<V>>::value))
constexpr explicit failure_type(V &&v, uint16_t spare_storage = 0)
: _exception(static_cast<V &&>(v)) // NOLINT
, _spare_storage(spare_storage)
{
}
constexpr exception_type &exception() & { return _exception; }
constexpr const exception_type &exception() const & { return _exception; }
constexpr exception_type &&exception() && { return static_cast<exception_type &&>(_exception); }
constexpr const exception_type &&exception() const && { return static_cast<exception_type &&>(_exception); }
constexpr uint16_t spare_storage() const { return _spare_storage; }
};
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class EC> inline constexpr failure_type<std::decay_t<EC>> failure(EC &&v, uint16_t spare_storage = 0)
{
return failure_type<std::decay_t<EC>>{static_cast<EC &&>(v), spare_storage};
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class EC, class E> inline constexpr failure_type<std::decay_t<EC>, std::decay_t<E>> failure(EC &&v, E &&w, uint16_t spare_storage = 0)
{
return failure_type<std::decay_t<EC>, std::decay_t<E>>{static_cast<EC &&>(v), static_cast<E &&>(w), spare_storage};
}
namespace detail
{
template <class T> struct is_success_type
{
static constexpr bool value = false;
};
template <class T> struct is_success_type<success_type<T>>
{
static constexpr bool value = true;
};
template <class T> struct is_failure_type
{
static constexpr bool value = false;
};
template <class EC, class E> struct is_failure_type<failure_type<EC, E>>
{
static constexpr bool value = true;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_success_type = detail::is_success_type<std::decay_t<T>>::value;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_failure_type = detail::is_failure_type<std::decay_t<T>>::value;
OUTCOME_V2_NAMESPACE_END
#endif
/* Traits for Outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (8 commits)
File Created: March 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_TRAIT_HPP
#define OUTCOME_TRAIT_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace trait
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R> //
static constexpr bool type_can_be_used_in_basic_result = //
(!std::is_reference<R>::value //
&& !OUTCOME_V2_NAMESPACE::detail::is_in_place_type_t<std::decay_t<R>>::value //
&& !is_success_type<R> //
&& !is_failure_type<R> //
&& !std::is_array<R>::value //
&& (std::is_void<R>::value || (std::is_object<R>::value //
&& std::is_destructible<R>::value)) //
);
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition is_error_type. Potential doc page: NOT FOUND
*/
template <class T> struct is_move_bitcopying
{
static constexpr bool value = false;
};
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition is_error_type. Potential doc page: NOT FOUND
*/
template <class E> struct is_error_type
{
static constexpr bool value = false;
};
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition is_error_type_enum. Potential doc page: NOT FOUND
*/
template <class E, class Enum> struct is_error_type_enum
{
static constexpr bool value = false;
};
namespace detail
{
template <class T> using devoid = OUTCOME_V2_NAMESPACE::detail::devoid<T>;
template <class T> std::add_rvalue_reference_t<devoid<T>> declval() noexcept;
// From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
namespace detector_impl
{
template <class...> using void_t = void;
template <class Default, class, template <class...> class Op, class... Args> struct detector
{
static constexpr bool value = false;
using type = Default;
};
template <class Default, template <class...> class Op, class... Args> struct detector<Default, void_t<Op<Args...>>, Op, Args...>
{
static constexpr bool value = true;
using type = Op<Args...>;
};
} // namespace detector_impl
template <template <class...> class Op, class... Args> using is_detected = detector_impl::detector<void, void, Op, Args...>;
template <class Arg> using result_of_make_error_code = decltype(make_error_code(declval<Arg>()));
template <class Arg> using introspect_make_error_code = is_detected<result_of_make_error_code, Arg>;
template <class Arg> using result_of_make_exception_ptr = decltype(make_exception_ptr(declval<Arg>()));
template <class Arg> using introspect_make_exception_ptr = is_detected<result_of_make_exception_ptr, Arg>;
template <class T> struct _is_error_code_available
{
static constexpr bool value = detail::introspect_make_error_code<T>::value;
using type = typename detail::introspect_make_error_code<T>::type;
};
template <class T> struct _is_exception_ptr_available
{
static constexpr bool value = detail::introspect_make_exception_ptr<T>::value;
using type = typename detail::introspect_make_exception_ptr<T>::type;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition is_error_code_available. Potential doc page: NOT FOUND
*/
template <class T> struct is_error_code_available
{
static constexpr bool value = detail::_is_error_code_available<std::decay_t<T>>::value;
using type = typename detail::_is_error_code_available<std::decay_t<T>>::type;
};
template <class T> constexpr bool is_error_code_available_v = detail::_is_error_code_available<std::decay_t<T>>::value;
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition is_exception_ptr_available. Potential doc page: NOT FOUND
*/
template <class T> struct is_exception_ptr_available
{
static constexpr bool value = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
using type = typename detail::_is_exception_ptr_available<std::decay_t<T>>::type;
};
template <class T> constexpr bool is_exception_ptr_available_v = detail::_is_exception_ptr_available<std::decay_t<T>>::value;
} // namespace trait
OUTCOME_V2_NAMESPACE_END
#endif
/* Essentially an internal optional implementation :)
(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (24 commits)
File Created: June 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_VALUE_STORAGE_HPP
#define OUTCOME_VALUE_STORAGE_HPP
#include <cassert>
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class T, bool nothrow> struct strong_swap_impl
{
constexpr strong_swap_impl(bool &allgood, T &a, T &b)
{
allgood = true;
using std::swap;
swap(a, b);
}
};
template <class T, bool nothrow> struct strong_placement_impl
{
template <class F> constexpr strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
{
allgood = true;
new(a) T(static_cast<T &&>(*b));
b->~T();
f();
}
};
#ifdef __cpp_exceptions
template <class T> struct strong_swap_impl<T, false>
{
strong_swap_impl(bool &allgood, T &a, T &b)
{
allgood = true;
T v(static_cast<T &&>(a));
try
{
a = static_cast<T &&>(b);
}
catch(...)
{
// Try to put back a
try
{
a = static_cast<T &&>(v);
// fall through as all good
}
catch(...)
{
// failed to completely restore
allgood = false;
// throw away second exception
}
throw; // rethrow original exception
}
// b has been moved to a, try to move v to b
try
{
b = static_cast<T &&>(v);
}
catch(...)
{
// Try to restore a to b, and v to a
try
{
b = static_cast<T &&>(a);
a = static_cast<T &&>(v);
// fall through as all good
}
catch(...)
{
// failed to completely restore
allgood = false;
// throw away second exception
}
throw; // rethrow original exception
}
}
};
template <class T> struct strong_placement_impl<T, false>
{
template <class F> strong_placement_impl(bool &allgood, T *a, T *b, F &&f)
{
new(a) T(static_cast<T &&>(*b));
try
{
b->~T();
f();
}
catch(...)
{
// Try to put back a, but only if we are still good
if(allgood)
{
try
{
new(b) T(static_cast<T &&>(*a));
// fall through as all good
}
catch(...)
{
// failed to completely restore
allgood = false;
// throw away second exception
}
throw; // rethrow original exception
}
}
}
};
#endif
} // namespace detail
/*!
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
constexpr inline void strong_swap(bool &allgood, T &a, T &b) noexcept(detail::is_nothrow_swappable<T>::value)
{
detail::strong_swap_impl<T, detail::is_nothrow_swappable<T>::value>(allgood, a, b);
}
/*!
*/
OUTCOME_TEMPLATE(class T, class F)
OUTCOME_TREQUIRES(OUTCOME_TPRED(std::is_move_constructible<T>::value &&std::is_move_assignable<T>::value))
constexpr inline void strong_placement(bool &allgood, T *a, T *b, F &&f) noexcept(std::is_nothrow_move_constructible<T>::value)
{
detail::strong_placement_impl<T, std::is_nothrow_move_constructible<T>::value>(allgood, a, b, static_cast<F &&>(f));
}
namespace detail
{
template <class T>
constexpr
#ifdef _MSC_VER
__declspec(noreturn)
#elif defined(__GNUC__) || defined(__clang__)
__attribute__((noreturn))
#endif
void make_ub(T && /*unused*/)
{
assert(false); // NOLINT
#if defined(__GNUC__) || defined(__clang__)
__builtin_unreachable();
#elif defined(_MSC_VER)
__assume(0);
#endif
}
/* Outcome v1 used a C bitfield whose values were tracked by compiler optimisers nicely,
but that produces ICEs when used in constexpr.
Outcome v2.0-v2.1 used a 32 bit integer and manually set and cleared bits. Unfortunately
only GCC's optimiser tracks bit values during constant folding, and only per byte, and
even then unreliably. https://wg21.link/P1886 "Error speed benchmarking" showed just how
poorly clang and MSVC fails to optimise outcome-using code, if you manually set bits.
Outcome v2.2 therefore uses an enum with fixed values, and constexpr manipulation functions
to change the value to one of the enum's values. This is stupid to look at in source code,
but it make clang's optimiser do the right thing, so it's worth it.
*/
#define OUTCOME_USE_CONSTEXPR_ENUM_STATUS 0
enum class status : uint16_t
{
// WARNING: These bits are not tracked by abi-dumper, but changing them will break ABI!
none = 0,
have_value = (1U << 0U),
have_error = (1U << 1U),
have_exception = (2U << 1U),
have_error_exception = (3U << 1U),
// failed to complete a strong swap
have_lost_consistency = (1U << 3U),
have_value_lost_consistency = (1U << 0U) | (1U << 3U),
have_error_lost_consistency = (1U << 1U) | (1U << 3U),
have_exception_lost_consistency = (2U << 1U) | (1U << 3U),
have_error_exception_lost_consistency = (3U << 1U) | (1U << 3U),
// can errno be set from this error?
have_error_is_errno = (1U << 4U),
have_error_error_is_errno = (1U << 1U) | (1U << 4U),
have_error_exception_error_is_errno = (3U << 1U) | (1U << 4U),
have_error_lost_consistency_error_is_errno = (1U << 1U) | (1U << 3U) | (1U << 4U),
have_error_exception_lost_consistency_error_is_errno = (3U << 1U) | (1U << 3U) | (1U << 4U),
// value has been moved from
have_moved_from = (1U << 5U)
};
struct status_bitfield_type
{
status status_value{status::none};
uint16_t spare_storage_value{0}; // hooks::spare_storage()
constexpr status_bitfield_type() = default;
constexpr status_bitfield_type(status v) noexcept
: status_value(v)
{
} // NOLINT
constexpr status_bitfield_type(status v, uint16_t s) noexcept
: status_value(v)
, spare_storage_value(s)
{
}
constexpr status_bitfield_type(const status_bitfield_type &) = default;
constexpr status_bitfield_type(status_bitfield_type &&) = default;
constexpr status_bitfield_type &operator=(const status_bitfield_type &) = default;
constexpr status_bitfield_type &operator=(status_bitfield_type &&) = default;
//~status_bitfield_type() = default; // Do NOT uncomment this, it breaks older clangs!
constexpr bool have_value() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_value)) != 0;
}
constexpr bool have_error() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error)) != 0;
}
constexpr bool have_exception() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_exception)) != 0;
}
constexpr bool have_lost_consistency() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_lost_consistency)) != 0;
}
constexpr bool have_error_is_errno() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_error_is_errno)) != 0;
}
constexpr bool have_moved_from() const noexcept
{
return (static_cast<uint16_t>(status_value) & static_cast<uint16_t>(status::have_moved_from)) != 0;
}
constexpr status_bitfield_type &set_have_value(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_value)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_value)));
return *this;
}
constexpr status_bitfield_type &set_have_error(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error)));
return *this;
}
constexpr status_bitfield_type &set_have_exception(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_exception)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_exception)));
return *this;
}
constexpr status_bitfield_type &set_have_error_is_errno(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_error_is_errno)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_error_is_errno)));
return *this;
}
constexpr status_bitfield_type &set_have_lost_consistency(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_lost_consistency)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_lost_consistency)));
return *this;
}
constexpr status_bitfield_type &set_have_moved_from(bool v) noexcept
{
status_value = static_cast<status>(v ? (static_cast<uint16_t>(status_value) | static_cast<uint16_t>(status::have_moved_from)) :
(static_cast<uint16_t>(status_value) & ~static_cast<uint16_t>(status::have_moved_from)));
return *this;
}
};
#if !defined(NDEBUG)
// Check is trivial in all ways except default constructibility
static_assert(sizeof(status_bitfield_type) == 4, "status_bitfield_type is not sized 4 bytes!");
static_assert(std::is_trivially_copyable<status_bitfield_type>::value, "status_bitfield_type is not trivially copyable!");
static_assert(std::is_trivially_assignable<status_bitfield_type, status_bitfield_type>::value, "status_bitfield_type is not trivially assignable!");
static_assert(std::is_trivially_destructible<status_bitfield_type>::value, "status_bitfield_type is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially copy constructible!");
static_assert(std::is_trivially_move_constructible<status_bitfield_type>::value, "status_bitfield_type is not trivially move constructible!");
static_assert(std::is_trivially_copy_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<status_bitfield_type>::value, "status_bitfield_type is not trivially move assignable!");
// Also check is standard layout
static_assert(std::is_standard_layout<status_bitfield_type>::value, "status_bitfield_type is not a standard layout type!");
#endif
template <class State> constexpr inline void _set_error_is_errno(State & /*unused*/) {}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4624) // destructor was implicitly defined as deleted
#endif
// Used if both T and E are trivial
template <class T, class E> struct value_storage_trivial
{
using value_type = T;
using error_type = E;
// Disable in place construction if they are the same type
struct disable_in_place_value_type
{
};
struct disable_in_place_error_type
{
};
using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
using _value_type_ = devoid<value_type>;
using _error_type_ = devoid<error_type>;
union {
empty_type _empty;
_value_type_ _value;
_error_type_ _error;
};
status_bitfield_type _status;
constexpr value_storage_trivial() noexcept
: _empty{}
{
}
value_storage_trivial(const value_storage_trivial &) = default; // NOLINT
value_storage_trivial(value_storage_trivial &&) = default; // NOLINT
value_storage_trivial &operator=(const value_storage_trivial &) = default; // NOLINT
value_storage_trivial &operator=(value_storage_trivial &&) = default; // NOLINT
~value_storage_trivial() = default;
constexpr explicit value_storage_trivial(status_bitfield_type status)
: _empty()
, _status(status)
{
}
template <class... Args>
constexpr explicit value_storage_trivial(in_place_type_t<_value_type> /*unused*/,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
: _value(static_cast<Args &&>(args)...)
, _status(status::have_value)
{
}
template <class U, class... Args>
constexpr value_storage_trivial(in_place_type_t<_value_type> /*unused*/, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
: _value(il, static_cast<Args &&>(args)...)
, _status(status::have_value)
{
}
template <class... Args>
constexpr explicit value_storage_trivial(in_place_type_t<_error_type> /*unused*/,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
: _error(static_cast<Args &&>(args)...)
, _status(status::have_error)
{
_set_error_is_errno(*this);
}
template <class U, class... Args>
constexpr value_storage_trivial(in_place_type_t<_error_type> /*unused*/, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
: _error(il, static_cast<Args &&>(args)...)
, _status(status::have_error)
{
_set_error_is_errno(*this);
}
struct nonvoid_converting_constructor_tag
{
};
template <class U, class V>
static constexpr bool enable_nonvoid_converting_constructor =
!(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value) //
&& detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_trivial(const value_storage_trivial<U, V> &o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_trivial(o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>, o._value) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_trivial(value_storage_trivial<U, V> &&o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_trivial(
o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
struct void_value_converting_constructor_tag
{
};
template <class V>
static constexpr bool enable_void_value_converting_constructor =
std::is_default_constructible<value_type>::value &&detail::is_constructible<error_type, V>;
OUTCOME_TEMPLATE(class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
constexpr explicit value_storage_trivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
std::is_nothrow_default_constructible<_value_type_>::value &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_trivial(o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, o._error) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
OUTCOME_TEMPLATE(class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
constexpr explicit value_storage_trivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
std::is_nothrow_default_constructible<_value_type_>::value &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_trivial(
o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
struct void_error_converting_constructor_tag
{
};
template <class U>
static constexpr bool enable_void_error_converting_constructor =
std::is_default_constructible<error_type>::value &&detail::is_constructible<value_type, U>;
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
constexpr explicit value_storage_trivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&std::is_nothrow_default_constructible<_error_type_>::value)
: value_storage_trivial(o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>, o._value) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
constexpr explicit value_storage_trivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&std::is_nothrow_default_constructible<_error_type_>::value)
: value_storage_trivial(o._status.have_value() ?
value_storage_trivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
(o._status.have_error() ? value_storage_trivial(in_place_type<error_type>) : value_storage_trivial())) // NOLINT
{
_status = o._status;
}
constexpr void swap(value_storage_trivial &o) noexcept
{
// storage is trivial, so just use assignment
auto temp = static_cast<value_storage_trivial &&>(*this);
*this = static_cast<value_storage_trivial &&>(o);
o = static_cast<value_storage_trivial &&>(temp);
}
};
// Used if T is non-trivial
template <class T, class E> struct value_storage_nontrivial
{
using value_type = T;
using error_type = E;
struct disable_in_place_value_type
{
};
struct disable_in_place_error_type
{
};
using _value_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_value_type, value_type>;
using _error_type = std::conditional_t<std::is_same<value_type, error_type>::value, disable_in_place_error_type, error_type>;
using _value_type_ = devoid<value_type>;
using _error_type_ = devoid<error_type>;
union {
empty_type _empty1;
_value_type_ _value;
};
status_bitfield_type _status;
union {
empty_type _empty2;
_error_type_ _error;
};
value_storage_nontrivial() noexcept
: _empty1{}
, _empty2{}
{
}
value_storage_nontrivial &operator=(const value_storage_nontrivial &) = default; // if reaches here, copy assignment is trivial
value_storage_nontrivial &operator=(value_storage_nontrivial &&) = default; // NOLINT if reaches here, move assignment is trivial
value_storage_nontrivial(value_storage_nontrivial &&o) noexcept(
std::is_nothrow_move_constructible<_value_type_>::value &&std::is_nothrow_move_constructible<_error_type_>::value) // NOLINT
{
if(o._status.have_value())
{
new(&_value) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
}
_status = o._status;
o._status.set_have_moved_from(true);
}
value_storage_nontrivial(const value_storage_nontrivial &o) noexcept(
std::is_nothrow_copy_constructible<_value_type_>::value &&std::is_nothrow_copy_constructible<_error_type_>::value)
{
if(o._status.have_value())
{
new(&_value) _value_type_(o._value); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(o._error); // NOLINT
}
_status = o._status;
}
explicit value_storage_nontrivial(status_bitfield_type status)
: _empty1()
, _status(status)
, _empty2()
{
}
template <class... Args>
explicit value_storage_nontrivial(in_place_type_t<_value_type> /*unused*/,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type_, Args...>)
: _value(static_cast<Args &&>(args)...) // NOLINT
, _status(status::have_value)
{
}
template <class U, class... Args>
value_storage_nontrivial(in_place_type_t<_value_type> /*unused*/, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type_, std::initializer_list<U>, Args...>)
: _value(il, static_cast<Args &&>(args)...)
, _status(status::have_value)
{
}
template <class... Args>
explicit value_storage_nontrivial(in_place_type_t<_error_type> /*unused*/,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type_, Args...>)
: _status(status::have_error)
, _error(static_cast<Args &&>(args)...) // NOLINT
{
_set_error_is_errno(*this);
}
template <class U, class... Args>
value_storage_nontrivial(in_place_type_t<_error_type> /*unused*/, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type_, std::initializer_list<U>, Args...>)
: _status(status::have_error)
, _error(il, static_cast<Args &&>(args)...)
{
_set_error_is_errno(*this);
}
struct nonvoid_converting_constructor_tag
{
};
template <class U, class V>
static constexpr bool enable_nonvoid_converting_constructor =
!(std::is_same<std::decay_t<U>, value_type>::value && std::is_same<std::decay_t<V>, error_type>::value) //
&& detail::is_constructible<value_type, U> && detail::is_constructible<error_type, V>;
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_nontrivial(const value_storage_trivial<U, V> &o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_nontrivial(o._status.have_value() ?
value_storage_nontrivial(in_place_type<value_type>, o._value) :
(o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
{
_status = o._status;
}
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_nontrivial(value_storage_trivial<U, V> &&o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_nontrivial(
o._status.have_value() ?
value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
(o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
{
_status = o._status;
}
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_nontrivial(const value_storage_nontrivial<U, V> &o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_nontrivial(o._status.have_value() ?
value_storage_nontrivial(in_place_type<value_type>, o._value) :
(o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, o._error) : value_storage_nontrivial()))
{
_status = o._status;
}
OUTCOME_TEMPLATE(class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_nonvoid_converting_constructor<U, V>))
constexpr explicit value_storage_nontrivial(value_storage_nontrivial<U, V> &&o, nonvoid_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&detail::is_nothrow_constructible<_error_type_, V>)
: value_storage_nontrivial(
o._status.have_value() ?
value_storage_nontrivial(in_place_type<value_type>, static_cast<U &&>(o._value)) :
(o._status.have_error() ? value_storage_nontrivial(in_place_type<error_type>, static_cast<V &&>(o._error)) : value_storage_nontrivial()))
{
_status = o._status;
}
struct void_value_converting_constructor_tag
{
};
template <class V>
static constexpr bool enable_void_value_converting_constructor =
std::is_default_constructible<value_type>::value &&detail::is_constructible<error_type, V>;
OUTCOME_TEMPLATE(class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
explicit value_storage_nontrivial(const value_storage_trivial<void, V> &o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
std::is_nothrow_default_constructible<_value_type_>::value &&detail::is_nothrow_constructible<_error_type_, V>)
{
if(o._status.have_value())
{
new(&_value) _value_type_(); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(o._error); // NOLINT
}
_status = o._status;
}
OUTCOME_TEMPLATE(class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_value_converting_constructor<V>))
explicit value_storage_nontrivial(value_storage_trivial<void, V> &&o, void_value_converting_constructor_tag /*unused*/ = {}) noexcept(
std::is_nothrow_default_constructible<_value_type_>::value &&detail::is_nothrow_constructible<_error_type_, V>)
{
if(o._status.have_value())
{
new(&_value) _value_type_(); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
}
_status = o._status;
o._status.set_have_moved_from(true);
}
struct void_error_converting_constructor_tag
{
};
template <class U>
static constexpr bool enable_void_error_converting_constructor =
std::is_default_constructible<error_type>::value &&detail::is_constructible<value_type, U>;
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
explicit value_storage_nontrivial(const value_storage_trivial<U, void> &o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&std::is_nothrow_default_constructible<_error_type_>::value)
{
if(o._status.have_value())
{
new(&_value) _value_type_(o._value); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(); // NOLINT
}
_status = o._status;
}
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(enable_void_error_converting_constructor<U>))
explicit value_storage_nontrivial(value_storage_trivial<U, void> &&o, void_error_converting_constructor_tag /*unused*/ = {}) noexcept(
detail::is_nothrow_constructible<_value_type_, U> &&std::is_nothrow_default_constructible<_error_type_>::value)
{
if(o._status.have_value())
{
new(&_value) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
}
else if(o._status.have_error())
{
new(&_error) _error_type_(); // NOLINT
}
_status = o._status;
o._status.set_have_moved_from(true);
}
~value_storage_nontrivial() noexcept(std::is_nothrow_destructible<_value_type_>::value &&std::is_nothrow_destructible<_error_type_>::value)
{
if(this->_status.have_value())
{
if(!trait::is_move_bitcopying<value_type>::value || !this->_status.have_moved_from())
{
this->_value.~_value_type_(); // NOLINT
}
this->_status.set_have_value(false);
}
else if(this->_status.have_error())
{
if(!trait::is_move_bitcopying<error_type>::value || !this->_status.have_moved_from())
{
this->_error.~_error_type_(); // NOLINT
}
this->_status.set_have_error(false);
}
}
constexpr void
swap(value_storage_nontrivial &o) noexcept(detail::is_nothrow_swappable<_value_type_>::value &&detail::is_nothrow_swappable<_error_type_>::value)
{
using std::swap;
// empty/empty
if(!_status.have_value() && !o._status.have_value() && !_status.have_error() && !o._status.have_error())
{
swap(_status, o._status);
return;
}
// value/value
if(_status.have_value() && o._status.have_value())
{
struct _
{
status_bitfield_type &a, &b;
bool all_good{false};
~_()
{
if(!all_good)
{
// We lost one of the values
a.set_have_lost_consistency(true);
b.set_have_lost_consistency(true);
}
}
} _{_status, o._status};
strong_swap(_.all_good, _value, o._value);
swap(_status, o._status);
return;
}
// error/error
if(_status.have_error() && o._status.have_error())
{
struct _
{
status_bitfield_type &a, &b;
bool all_good{false};
~_()
{
if(!all_good)
{
// We lost one of the values
a.set_have_lost_consistency(true);
b.set_have_lost_consistency(true);
}
}
} _{_status, o._status};
strong_swap(_.all_good, _error, o._error);
swap(_status, o._status);
return;
}
// Could be value/empty, error/empty, etc
if(_status.have_value() && !o._status.have_error())
{
// Move construct me into other
new(&o._value) _value_type_(static_cast<_value_type_ &&>(_value)); // NOLINT
if(!trait::is_move_bitcopying<value_type>::value)
{
this->_value.~value_type(); // NOLINT
}
swap(_status, o._status);
return;
}
if(o._status.have_value() && !_status.have_error())
{
// Move construct other into me
new(&_value) _value_type_(static_cast<_value_type_ &&>(o._value)); // NOLINT
if(!trait::is_move_bitcopying<value_type>::value)
{
o._value.~value_type(); // NOLINT
}
swap(_status, o._status);
return;
}
if(_status.have_error() && !o._status.have_value())
{
// Move construct me into other
new(&o._error) _error_type_(static_cast<_error_type_ &&>(_error)); // NOLINT
if(!trait::is_move_bitcopying<error_type>::value)
{
this->_error.~error_type(); // NOLINT
}
swap(_status, o._status);
return;
}
if(o._status.have_error() && !_status.have_value())
{
// Move construct other into me
new(&_error) _error_type_(static_cast<_error_type_ &&>(o._error)); // NOLINT
if(!trait::is_move_bitcopying<error_type>::value)
{
o._error.~error_type(); // NOLINT
}
swap(_status, o._status);
return;
}
// It can now only be value/error, or error/value
struct _
{
status_bitfield_type &a, &b;
_value_type_ *value, *o_value;
_error_type_ *error, *o_error;
bool all_good{true};
~_()
{
if(!all_good)
{
// We lost one of the values
a.set_have_lost_consistency(true);
b.set_have_lost_consistency(true);
}
}
} _{_status, o._status, &_value, &o._value, &_error, &o._error};
if(_status.have_value() && o._status.have_error())
{
strong_placement(_.all_good, _.o_value, _.value, [&_] { //
strong_placement(_.all_good, _.error, _.o_error, [&_] { //
swap(_.a, _.b); //
});
});
return;
}
if(_status.have_error() && o._status.have_value())
{
strong_placement(_.all_good, _.o_error, _.error, [&_] { //
strong_placement(_.all_good, _.value, _.o_value, [&_] { //
swap(_.a, _.b); //
});
});
return;
}
// Should never reach here
make_ub(_value);
}
};
template <class Base> struct value_storage_delete_copy_constructor : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_delete_copy_constructor() = default;
value_storage_delete_copy_constructor(const value_storage_delete_copy_constructor &) = delete;
value_storage_delete_copy_constructor(value_storage_delete_copy_constructor &&) = default; // NOLINT
};
template <class Base> struct value_storage_delete_copy_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_delete_copy_assignment() = default;
value_storage_delete_copy_assignment(const value_storage_delete_copy_assignment &) = default;
value_storage_delete_copy_assignment(value_storage_delete_copy_assignment &&) = default; // NOLINT
value_storage_delete_copy_assignment &operator=(const value_storage_delete_copy_assignment &o) = delete;
value_storage_delete_copy_assignment &operator=(value_storage_delete_copy_assignment &&o) = default; // NOLINT
};
template <class Base> struct value_storage_delete_move_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_delete_move_assignment() = default;
value_storage_delete_move_assignment(const value_storage_delete_move_assignment &) = default;
value_storage_delete_move_assignment(value_storage_delete_move_assignment &&) = default; // NOLINT
value_storage_delete_move_assignment &operator=(const value_storage_delete_move_assignment &o) = default;
value_storage_delete_move_assignment &operator=(value_storage_delete_move_assignment &&o) = delete;
};
template <class Base> struct value_storage_delete_move_constructor : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_delete_move_constructor() = default;
value_storage_delete_move_constructor(const value_storage_delete_move_constructor &) = default;
value_storage_delete_move_constructor(value_storage_delete_move_constructor &&) = delete;
};
template <class Base> struct value_storage_nontrivial_move_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_nontrivial_move_assignment() = default;
value_storage_nontrivial_move_assignment(const value_storage_nontrivial_move_assignment &) = default;
value_storage_nontrivial_move_assignment(value_storage_nontrivial_move_assignment &&) = default; // NOLINT
value_storage_nontrivial_move_assignment &operator=(const value_storage_nontrivial_move_assignment &o) = default;
value_storage_nontrivial_move_assignment &operator=(value_storage_nontrivial_move_assignment &&o) noexcept(
std::is_nothrow_move_assignable<value_type>::value &&std::is_nothrow_move_assignable<error_type>::value) // NOLINT
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
{
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_value() && o._status.have_value())
{
this->_value = static_cast<_value_type_&&>(o._value); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_error() && o._status.have_error())
{
this->_error = static_cast<_error_type_&&>(o._error); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
{
if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
{
this->_value.~_value_type_(); // NOLINT
}
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
new(&this->_value) _value_type_(static_cast<_value_type_&&>(o._value)); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
{
if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
{
this->_error.~_error_type_(); // NOLINT
}
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
new(&this->_error) _error_type_(static_cast<_error_type_&&>(o._error)); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_value() && o._status.have_error())
{
if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
{
this->_value.~_value_type_(); // NOLINT
}
new(&this->_error) _error_type_(static_cast<_error_type_&&>(o._error)); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
if(this->_status.have_error() && o._status.have_value())
{
if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
{
this->_error.~_error_type_(); // NOLINT
}
new(&this->_value) _value_type_(static_cast<_value_type_&&>(o._value)); // NOLINT
this->_status = o._status;
o._status.set_have_moved_from(true);
return *this;
}
// Should never reach here
make_ub(this->_value);
}
};
template <class Base> struct value_storage_nontrivial_copy_assignment : Base // NOLINT
{
using Base::Base;
using value_type = typename Base::value_type;
using error_type = typename Base::error_type;
value_storage_nontrivial_copy_assignment() = default;
value_storage_nontrivial_copy_assignment(const value_storage_nontrivial_copy_assignment &) = default;
value_storage_nontrivial_copy_assignment(value_storage_nontrivial_copy_assignment &&) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(value_storage_nontrivial_copy_assignment &&o) = default; // NOLINT
value_storage_nontrivial_copy_assignment &operator=(const value_storage_nontrivial_copy_assignment &o) noexcept(
std::is_nothrow_copy_assignable<value_type>::value &&std::is_nothrow_copy_assignable<error_type>::value)
{
using _value_type_ = typename Base::_value_type_;
using _error_type_ = typename Base::_error_type_;
if(!this->_status.have_value() && !this->_status.have_error() && !o._status.have_value()
&& !o._status.have_error())
{
this->_status = o._status;
return *this;
}
if(this->_status.have_value() && o._status.have_value())
{
this->_value = o._value; // NOLINT
this->_status = o._status;
return *this;
}
if(this->_status.have_error() && o._status.have_error())
{
this->_error = o._error; // NOLINT
this->_status = o._status;
return *this;
}
if(this->_status.have_value() && !o._status.have_value() && !o._status.have_error())
{
if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
{
this->_value.~_value_type_(); // NOLINT
}
this->_status = o._status;
return *this;
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_value())
{
new(&this->_value) _value_type_(o._value); // NOLINT
this->_status = o._status;
return *this;
}
if(this->_status.have_error() && !o._status.have_value() && !o._status.have_error())
{
if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
{
this->_error.~_error_type_(); // NOLINT
}
this->_status = o._status;
return *this;
}
if(!this->_status.have_value() && !this->_status.have_error() && o._status.have_error())
{
new(&this->_error) _error_type_(o._error); // NOLINT
this->_status = o._status;
return *this;
}
if(this->_status.have_value() && o._status.have_error())
{
if(!trait::is_move_bitcopying<value_type>::value || this->_status.have_moved_from())
{
this->_value.~_value_type_(); // NOLINT
}
new(&this->_error) _error_type_(o._error); // NOLINT
this->_status = o._status;
return *this;
}
if(this->_status.have_error() && o._status.have_value())
{
if(!trait::is_move_bitcopying<error_type>::value || this->_status.have_moved_from())
{
this->_error.~_error_type_(); // NOLINT
}
new(&this->_value) _value_type_(o._value); // NOLINT
this->_status = o._status;
return *this;
}
// Should never reach here
make_ub(this->_value);
}
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// is_trivially_copyable is true even if type is not copyable, so handle that here
template <class T> struct is_storage_trivial
{
static constexpr bool value = std::is_void<T>::value || (std::is_trivially_copy_constructible<T>::value && std::is_trivially_copyable<T>::value);
};
// work around libstdc++ 7 bug
template <> struct is_storage_trivial<void>
{
static constexpr bool value = true;
};
template <> struct is_storage_trivial<const void>
{
static constexpr bool value = true;
};
template <class T, class E>
using value_storage_select_trivality =
std::conditional_t<is_storage_trivial<T>::value && is_storage_trivial<E>::value, value_storage_trivial<T, E>, value_storage_nontrivial<T, E>>;
template <class T, class E>
using value_storage_select_move_constructor =
std::conditional_t<std::is_move_constructible<devoid<T>>::value && std::is_move_constructible<devoid<E>>::value, value_storage_select_trivality<T, E>,
value_storage_delete_move_constructor<value_storage_select_trivality<T, E>>>;
template <class T, class E>
using value_storage_select_copy_constructor =
std::conditional_t<std::is_copy_constructible<devoid<T>>::value && std::is_copy_constructible<devoid<E>>::value, value_storage_select_move_constructor<T, E>,
value_storage_delete_copy_constructor<value_storage_select_move_constructor<T, E>>>;
template <class T, class E>
using value_storage_select_move_assignment =
std::conditional_t<std::is_trivially_move_assignable<devoid<T>>::value && std::is_trivially_move_assignable<devoid<E>>::value,
value_storage_select_copy_constructor<T, E>,
std::conditional_t<std::is_move_assignable<devoid<T>>::value && std::is_move_assignable<devoid<E>>::value,
value_storage_nontrivial_move_assignment<value_storage_select_copy_constructor<T, E>>,
value_storage_delete_copy_assignment<value_storage_select_copy_constructor<T, E>>>>;
template <class T, class E>
using value_storage_select_copy_assignment =
std::conditional_t<std::is_trivially_copy_assignable<devoid<T>>::value && std::is_trivially_copy_assignable<devoid<E>>::value,
value_storage_select_move_assignment<T, E>,
std::conditional_t<std::is_copy_assignable<devoid<T>>::value && std::is_copy_assignable<devoid<E>>::value,
value_storage_nontrivial_copy_assignment<value_storage_select_move_assignment<T, E>>,
value_storage_delete_copy_assignment<value_storage_select_move_assignment<T, E>>>>;
template <class T, class E> using value_storage_select_impl = value_storage_select_copy_assignment<T, E>;
#ifndef NDEBUG
// Check is trivial in all ways except default constructibility
// static_assert(std::is_trivial<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivial!");
// static_assert(std::is_trivially_default_constructible<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivially
// default constructible!");
static_assert(std::is_trivially_copyable<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not trivially copyable!");
static_assert(std::is_trivially_assignable<value_storage_select_impl<int, long>, value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially assignable!");
static_assert(std::is_trivially_destructible<value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially copy constructible!");
static_assert(std::is_trivially_move_constructible<value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially move constructible!");
static_assert(std::is_trivially_copy_assignable<value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<value_storage_select_impl<int, long>>::value,
"value_storage_select_impl<int, long> is not trivially move assignable!");
// Also check is standard layout
static_assert(std::is_standard_layout<value_storage_select_impl<int, long>>::value, "value_storage_select_impl<int, long> is not a standard layout type!");
#endif
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class R, class EC, class NoValuePolicy> class basic_result_storage;
} // namespace detail
namespace hooks
{
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_storage<R, S, NoValuePolicy> *r) noexcept;
template <class R, class S, class NoValuePolicy>
constexpr inline void set_spare_storage(detail::basic_result_storage<R, S, NoValuePolicy> *r, uint16_t v) noexcept;
} // namespace hooks
namespace policy
{
struct base;
} // namespace policy
namespace detail
{
template <class R, class EC, class NoValuePolicy> //
class basic_result_storage
{
static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
static_assert(trait::type_can_be_used_in_basic_result<EC>, "The type S cannot be used in a basic_result");
friend struct policy::base;
template <class T, class U, class V> //
friend class basic_result_storage;
template <class T, class U, class V> friend class basic_result_final;
template <class T, class U, class V>
friend constexpr inline uint16_t hooks::spare_storage(const detail::basic_result_storage<T, U, V> *r) noexcept; // NOLINT
template <class T, class U, class V>
friend constexpr inline void hooks::set_spare_storage(detail::basic_result_storage<T, U, V> *r, uint16_t v) noexcept; // NOLINT
struct disable_in_place_value_type
{
};
struct disable_in_place_error_type
{
};
protected:
using _value_type = std::conditional_t<std::is_same<R, EC>::value, disable_in_place_value_type, R>;
using _error_type = std::conditional_t<std::is_same<R, EC>::value, disable_in_place_error_type, EC>;
using _state_type = value_storage_select_impl<_value_type, _error_type>;
_state_type _state;
public:
// Used by iostream support to access state
_state_type &_iostreams_state() { return _state; }
const _state_type &_iostreams_state() const { return _state; }
protected:
basic_result_storage() = default;
basic_result_storage(const basic_result_storage &) = default; // NOLINT
basic_result_storage(basic_result_storage &&) = default; // NOLINT
basic_result_storage &operator=(const basic_result_storage &) = default; // NOLINT
basic_result_storage &operator=(basic_result_storage &&) = default; // NOLINT
~basic_result_storage() = default;
template <class... Args>
constexpr explicit basic_result_storage(in_place_type_t<_value_type> _,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type, Args...>)
: _state{_, static_cast<Args &&>(args)...}
{
}
template <class U, class... Args>
constexpr basic_result_storage(in_place_type_t<_value_type> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_value_type, std::initializer_list<U>, Args...>)
: _state{_, il, static_cast<Args &&>(args)...}
{
}
template <class... Args>
constexpr explicit basic_result_storage(in_place_type_t<_error_type> _,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type, Args...>)
: _state{_, static_cast<Args &&>(args)...}
{
}
template <class U, class... Args>
constexpr basic_result_storage(in_place_type_t<_error_type> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<_error_type, std::initializer_list<U>, Args...>)
: _state{_, il, static_cast<Args &&>(args)...}
{
}
struct compatible_conversion_tag
{
};
template <class T, class U, class V>
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&detail::is_nothrow_constructible<_error_type, U>)
: _state(o._state)
{
}
template <class T, class U, class V>
constexpr basic_result_storage(compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&detail::is_nothrow_constructible<_error_type, U>)
: _state(static_cast<decltype(o._state) &&>(o._state))
{
}
struct make_error_code_compatible_conversion_tag
{
};
template <class T, class U, class V>
constexpr basic_result_storage(make_error_code_compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_error_code(std::declval<U>())))
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, o._state._value) :
_state_type(in_place_type<_error_type>, make_error_code(o._state._error)))
{
}
template <class T, class U, class V>
constexpr basic_result_storage(make_error_code_compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_error_code(std::declval<U>())))
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, static_cast<T &&>(o._state._value)) :
_state_type(in_place_type<_error_type>, make_error_code(static_cast<U &&>(o._state._error))))
{
}
struct make_exception_ptr_compatible_conversion_tag
{
};
template <class T, class U, class V>
constexpr basic_result_storage(make_exception_ptr_compatible_conversion_tag /*unused*/, const basic_result_storage<T, U, V> &o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_exception_ptr(std::declval<U>())))
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, o._state._value) :
_state_type(in_place_type<_error_type>, make_exception_ptr(o._state._error)))
{
}
template <class T, class U, class V>
constexpr basic_result_storage(make_exception_ptr_compatible_conversion_tag /*unused*/, basic_result_storage<T, U, V> &&o) noexcept(
detail::is_nothrow_constructible<_value_type, T> &&noexcept(make_exception_ptr(std::declval<U>())))
: _state(o._state._status.have_value() ? _state_type(in_place_type<_value_type>, static_cast<T &&>(o._state._value)) :
_state_type(in_place_type<_error_type>, make_exception_ptr(static_cast<U &&>(o._state._error))))
{
}
};
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace concepts
{
#if defined(__cpp_concepts)
#if (defined(_MSC_VER) || defined(__clang__) || (defined(__GNUC__) && __cpp_concepts >= 201707) || OUTCOME_FORCE_STD_CXX_CONCEPTS) && !OUTCOME_FORCE_LEGACY_GCC_CXX_CONCEPTS
#define OUTCOME_GCC6_CONCEPT_BOOL
#else
#define OUTCOME_GCC6_CONCEPT_BOOL bool
#endif
namespace detail
{
template <class T, class U> concept OUTCOME_GCC6_CONCEPT_BOOL SameHelper = std::is_same<T, U>::value;
template <class T, class U> concept OUTCOME_GCC6_CONCEPT_BOOL same_as = detail::SameHelper<T, U> &&detail::SameHelper<U, T>;
template <class T, class U> concept OUTCOME_GCC6_CONCEPT_BOOL convertible = std::is_convertible<T, U>::value;
template <class T, class U> concept OUTCOME_GCC6_CONCEPT_BOOL base_of = std::is_base_of<T, U>::value;
} // namespace detail
/* The `value_or_none` concept.
\requires That `U::value_type` exists and that `std::declval<U>().has_value()` returns a `bool` and `std::declval<U>().value()` exists.
*/
template <class U> concept OUTCOME_GCC6_CONCEPT_BOOL value_or_none = requires(U a)
{
{
a.has_value()
}
->detail::same_as<bool>;
{a.value()};
};
/* The `value_or_error` concept.
\requires That `U::value_type` and `U::error_type` exist;
that `std::declval<U>().has_value()` returns a `bool`, `std::declval<U>().value()` and `std::declval<U>().error()` exists.
*/
template <class U> concept OUTCOME_GCC6_CONCEPT_BOOL value_or_error = requires(U a)
{
{
a.has_value()
}
->detail::same_as<bool>;
{a.value()};
{a.error()};
};
#else
namespace detail
{
struct no_match
{
};
inline no_match match_value_or_none(...);
inline no_match match_value_or_error(...);
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<U>().has_value()), OUTCOME_TEXPR(std::declval<U>().value()))
inline U match_value_or_none(U &&);
OUTCOME_TEMPLATE(class U)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<U>().has_value()), OUTCOME_TEXPR(std::declval<U>().value()), OUTCOME_TEXPR(std::declval<U>().error()))
inline U match_value_or_error(U &&);
template <class U>
static constexpr bool value_or_none =
!std::is_same<no_match, decltype(match_value_or_none(std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
template <class U>
static constexpr bool value_or_error =
!std::is_same<no_match, decltype(match_value_or_error(std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
} // namespace detail
/* The `value_or_none` concept.
\requires That `U::value_type` exists and that `std::declval<U>().has_value()` returns a `bool` and `std::declval<U>().value()` exists.
*/
template <class U> static constexpr bool value_or_none = detail::value_or_none<U>;
/* The `value_or_error` concept.
\requires That `U::value_type` and `U::error_type` exist;
that `std::declval<U>().has_value()` returns a `bool`, `std::declval<U>().value()` and `std::declval<U>().error()` exists.
*/
template <class U> static constexpr bool value_or_error = detail::value_or_error<U>;
#endif
} // namespace concepts
namespace convert
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
#if defined(__cpp_concepts)
template <class U> concept OUTCOME_GCC6_CONCEPT_BOOL ValueOrNone = concepts::value_or_none<U>;
template <class U> concept OUTCOME_GCC6_CONCEPT_BOOL ValueOrError = concepts::value_or_error<U>;
#else
template <class U> static constexpr bool ValueOrNone = concepts::value_or_none<U>;
template <class U> static constexpr bool ValueOrError = concepts::value_or_error<U>;
#endif
#endif
namespace detail
{
template <class T, class X> struct make_type
{
template <class U> static constexpr T value(U &&v) { return T{in_place_type<typename T::value_type>, static_cast<U &&>(v).value()}; }
template <class U> static constexpr T error(U &&v) { return T{in_place_type<typename T::error_type>, static_cast<U &&>(v).error()}; }
static constexpr T error() { return T{in_place_type<typename T::error_type>}; }
};
template <class T> struct make_type<T, void>
{
template <class U> static constexpr T value(U && /*unused*/) { return T{in_place_type<typename T::value_type>}; }
template <class U> static constexpr T error(U && /*unused*/) { return T{in_place_type<typename T::error_type>}; }
static constexpr T error() { return T{in_place_type<typename T::error_type>}; }
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition value_or_error. Potential doc page: NOT FOUND
*/
template <class T, class U> struct value_or_error
{
static constexpr bool enable_result_inputs = false;
static constexpr bool enable_outcome_inputs = false;
OUTCOME_TEMPLATE(class X)
OUTCOME_TREQUIRES(
OUTCOME_TPRED(std::is_same<U, std::decay_t<X>>::value //
&&concepts::value_or_error<U> //
&& (std::is_void<typename std::decay_t<X>::value_type>::value ||
OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::value_type, typename std::decay_t<X>::value_type>) //
&&(std::is_void<typename std::decay_t<X>::error_type>::value ||
OUTCOME_V2_NAMESPACE::detail::is_explicitly_constructible<typename T::error_type, typename std::decay_t<X>::error_type>) ))
constexpr T operator()(X &&v)
{
return v.has_value() ? detail::make_type<T, typename T::value_type>::value(static_cast<X &&>(v)) :
detail::make_type<T, typename U::error_type>::error(static_cast<X &&>(v));
}
};
} // namespace convert
OUTCOME_V2_NAMESPACE_END
#endif
/* Finaliser for a very simple result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_RESULT_FINAL_HPP
#define OUTCOME_BASIC_RESULT_FINAL_HPP
/* Error observers for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_RESULT_ERROR_OBSERVERS_HPP
#define OUTCOME_BASIC_RESULT_ERROR_OBSERVERS_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class EC, class NoValuePolicy> class basic_result_error_observers : public Base
{
public:
using error_type = EC;
using Base::Base;
constexpr error_type &assume_error() & noexcept
{
NoValuePolicy::narrow_error_check(static_cast<basic_result_error_observers &>(*this));
return this->_state._error;
}
constexpr const error_type &assume_error() const &noexcept
{
NoValuePolicy::narrow_error_check(static_cast<const basic_result_error_observers &>(*this));
return this->_state._error;
}
constexpr error_type &&assume_error() && noexcept
{
NoValuePolicy::narrow_error_check(static_cast<basic_result_error_observers &&>(*this));
return static_cast<error_type &&>(this->_state._error);
}
constexpr const error_type &&assume_error() const &&noexcept
{
NoValuePolicy::narrow_error_check(static_cast<const basic_result_error_observers &&>(*this));
return static_cast<const error_type &&>(this->_state._error);
}
constexpr error_type &error() &
{
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &>(*this));
return this->_state._error;
}
constexpr const error_type &error() const &
{
NoValuePolicy::wide_error_check(static_cast<const basic_result_error_observers &>(*this));
return this->_state._error;
}
constexpr error_type &&error() &&
{
NoValuePolicy::wide_error_check(static_cast<basic_result_error_observers &&>(*this));
return static_cast<error_type &&>(this->_state._error);
}
constexpr const error_type &&error() const &&
{
NoValuePolicy::wide_error_check(static_cast<const basic_result_error_observers &&>(*this));
return static_cast<const error_type &&>(this->_state._error);
}
};
template <class Base, class NoValuePolicy> class basic_result_error_observers<Base, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_error() const noexcept { NoValuePolicy::narrow_error_check(*this); }
constexpr void error() const { NoValuePolicy::wide_error_check(*this); }
};
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
/* Value observers for a very simple basic_result type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (2 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_RESULT_VALUE_OBSERVERS_HPP
#define OUTCOME_RESULT_VALUE_OBSERVERS_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class R, class NoValuePolicy> class basic_result_value_observers : public Base
{
public:
using value_type = R;
using Base::Base;
constexpr value_type &assume_value() & noexcept
{
NoValuePolicy::narrow_value_check(static_cast<basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr const value_type &assume_value() const &noexcept
{
NoValuePolicy::narrow_value_check(static_cast<const basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr value_type &&assume_value() && noexcept
{
NoValuePolicy::narrow_value_check(static_cast<basic_result_value_observers &&>(*this));
return static_cast<value_type &&>(this->_state._value); // NOLINT
}
constexpr const value_type &&assume_value() const &&noexcept
{
NoValuePolicy::narrow_value_check(static_cast<const basic_result_value_observers &&>(*this));
return static_cast<const value_type &&>(this->_state._value); // NOLINT
}
constexpr value_type &value() &
{
NoValuePolicy::wide_value_check(static_cast<basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr const value_type &value() const &
{
NoValuePolicy::wide_value_check(static_cast<const basic_result_value_observers &>(*this));
return this->_state._value; // NOLINT
}
constexpr value_type &&value() &&
{
NoValuePolicy::wide_value_check(static_cast<basic_result_value_observers &&>(*this));
return static_cast<value_type &&>(this->_state._value); // NOLINT
}
constexpr const value_type &&value() const &&
{
NoValuePolicy::wide_value_check(static_cast<const basic_result_value_observers &&>(*this));
return static_cast<const value_type &&>(this->_state._value); // NOLINT
}
};
template <class Base, class NoValuePolicy> class basic_result_value_observers<Base, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_value() const noexcept { NoValuePolicy::narrow_value_check(*this); }
constexpr void value() const { NoValuePolicy::wide_value_check(*this); }
};
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class R, class EC, class NoValuePolicy> using select_basic_result_impl = basic_result_error_observers<basic_result_value_observers<basic_result_storage<R, EC, NoValuePolicy>, R, NoValuePolicy>, EC, NoValuePolicy>;
template <class R, class S, class NoValuePolicy>
class basic_result_final
: public select_basic_result_impl<R, S, NoValuePolicy>
{
using base = select_basic_result_impl<R, S, NoValuePolicy>;
public:
using base::base;
constexpr explicit operator bool() const noexcept { return this->_state._status.have_value(); }
constexpr bool has_value() const noexcept { return this->_state._status.have_value(); }
constexpr bool has_error() const noexcept { return this->_state._status.have_error(); }
constexpr bool has_exception() const noexcept { return this->_state._status.have_exception(); }
constexpr bool has_lost_consistency() const noexcept { return this->_state._status.have_lost_consistency(); }
constexpr bool has_failure() const noexcept { return this->_state._status.have_error() || this->_state._status.have_exception(); }
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<detail::devoid<R>>() == std::declval<detail::devoid<T>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<S>>() == std::declval<detail::devoid<U>>()))
constexpr bool operator==(const basic_result_final<T, U, V> &o) const noexcept( //
noexcept(std::declval<detail::devoid<R>>() == std::declval<detail::devoid<T>>()) && noexcept(std::declval<detail::devoid<S>>() == std::declval<detail::devoid<U>>()))
{
if(this->_state._status.have_value() && o._state._status.have_value())
{
return this->_state._value == o._state._value; // NOLINT
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error == o._state._error;
}
return false;
}
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<R>() == std::declval<T>()))
constexpr bool operator==(const success_type<T> &o) const noexcept( //
noexcept(std::declval<R>() == std::declval<T>()))
{
if(this->_state._status.have_value())
{
return this->_state._value == o.value();
}
return false;
}
constexpr bool operator==(const success_type<void> &o) const noexcept
{
(void) o;
return this->_state._status.have_value();
}
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<S>() == std::declval<T>()))
constexpr bool operator==(const failure_type<T, void> &o) const noexcept( //
noexcept(std::declval<S>() == std::declval<T>()))
{
if(this->_state._status.have_error())
{
return this->_state._error == o.error();
}
return false;
}
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<detail::devoid<R>>() != std::declval<detail::devoid<T>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<S>>() != std::declval<detail::devoid<U>>()))
constexpr bool operator!=(const basic_result_final<T, U, V> &o) const noexcept( //
noexcept(std::declval<detail::devoid<R>>() != std::declval<detail::devoid<T>>()) && noexcept(std::declval<detail::devoid<S>>() != std::declval<detail::devoid<U>>()))
{
if(this->_state._status.have_value() && o._state._status.have_value())
{
return this->_state._value != o._state._value;
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error != o._state._error;
}
return true;
}
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<R>() != std::declval<T>()))
constexpr bool operator!=(const success_type<T> &o) const noexcept( //
noexcept(std::declval<R>() != std::declval<T>()))
{
if(this->_state._status.have_value())
{
return this->_state._value != o.value();
}
return false;
}
constexpr bool operator!=(const success_type<void> &o) const noexcept
{
(void) o;
return !this->_state._status.have_value();
}
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<S>() != std::declval<T>()))
constexpr bool operator!=(const failure_type<T, void> &o) const noexcept( //
noexcept(std::declval<S>() != std::declval<T>()))
{
if(this->_state._status.have_error())
{
return this->_state._error != o.error();
}
return true;
}
};
template <class T, class U, class V, class W> constexpr inline bool operator==(const success_type<W> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b == a; }
template <class T, class U, class V, class W> constexpr inline bool operator==(const failure_type<W, void> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b == a; }
template <class T, class U, class V, class W> constexpr inline bool operator!=(const success_type<W> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b != a; }
template <class T, class U, class V, class W> constexpr inline bool operator!=(const failure_type<W, void> &a, const basic_result_final<T, U, V> &b) noexcept(noexcept(b == a)) { return b != a; }
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (13 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_POLICY_ALL_NARROW_HPP
#define OUTCOME_POLICY_ALL_NARROW_HPP
/* Policies for result and outcome
(C) 2017-2020 Niall Douglas <http://www.nedproductions.biz/> (6 commits) and Andrzej Krzemieński <akrzemi1@gmail.com> (1 commit)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_POLICY_BASE_HPP
#define OUTCOME_POLICY_BASE_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
namespace hooks
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U> constexpr inline void hook_result_construction(T * /*unused*/, U && /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U> constexpr inline void hook_result_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U> constexpr inline void hook_result_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U, class... Args>
constexpr inline void hook_result_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class... U> constexpr inline void hook_outcome_construction(T * /*unused*/, U &&... /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U> constexpr inline void hook_outcome_copy_construction(T * /*unused*/, U && /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U> constexpr inline void hook_outcome_move_construction(T * /*unused*/, U && /*unused*/) noexcept {}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T, class U, class... Args>
constexpr inline void hook_outcome_in_place_construction(T * /*unused*/, in_place_type_t<U> /*unused*/, Args &&... /*unused*/) noexcept
{
}
} // namespace hooks
#endif
namespace policy
{
namespace detail
{
using OUTCOME_V2_NAMESPACE::detail::make_ub;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
struct base
{
template <class... Args> static constexpr void _silence_unused(Args &&... /*unused*/) noexcept {}
protected:
template <class Impl> static constexpr void _make_ub(Impl &&self) noexcept { return detail::make_ub(static_cast<Impl &&>(self)); }
template <class Impl> static constexpr bool _has_value(Impl &&self) noexcept { return self._state._status.have_value(); }
template <class Impl> static constexpr bool _has_error(Impl &&self) noexcept { return self._state._status.have_error(); }
template <class Impl> static constexpr bool _has_exception(Impl &&self) noexcept { return self._state._status.have_exception(); }
template <class Impl> static constexpr bool _has_error_is_errno(Impl &&self) noexcept { return self._state._status.have_error_is_errno(); }
template <class Impl> static constexpr void _set_has_value(Impl &&self, bool v) noexcept { self._state._status.set_have_value(v); }
template <class Impl> static constexpr void _set_has_error(Impl &&self, bool v) noexcept { self._state._status.set_have_error(v); }
template <class Impl> static constexpr void _set_has_exception(Impl &&self, bool v) noexcept { self._state._status.set_have_exception(v); }
template <class Impl> static constexpr void _set_has_error_is_errno(Impl &&self, bool v) noexcept { self._state._status.set_have_error_is_errno(v); }
template <class Impl> static constexpr auto &&_value(Impl &&self) noexcept { return static_cast<Impl &&>(self)._state._value; }
template <class Impl> static constexpr auto &&_error(Impl &&self) noexcept { return static_cast<Impl &&>(self)._state._error; }
public:
template <class R, class S, class P, class NoValuePolicy, class Impl> static inline constexpr auto &&_exception(Impl &&self) noexcept;
template <class T, class U> static constexpr inline void on_result_construction(T *inst, U &&v) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_result_construction(inst, static_cast<U &&>(v));
#else
(void) inst;
(void) v;
#endif
}
template <class T, class U> static constexpr inline void on_result_copy_construction(T *inst, U &&v) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_result_copy_construction(inst, static_cast<U &&>(v));
#else
(void) inst;
(void) v;
#endif
}
template <class T, class U> static constexpr inline void on_result_move_construction(T *inst, U &&v) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_result_move_construction(inst, static_cast<U &&>(v));
#else
(void) inst;
(void) v;
#endif
}
template <class T, class U, class... Args>
static constexpr inline void on_result_in_place_construction(T *inst, in_place_type_t<U> _, Args &&... args) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_result_in_place_construction(inst, _, static_cast<Args &&>(args)...);
#else
(void) inst;
(void) _;
_silence_unused(static_cast<Args &&>(args)...);
#endif
}
template <class T, class... U> static constexpr inline void on_outcome_construction(T *inst, U &&... args) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_outcome_construction(inst, static_cast<U &&>(args)...);
#else
(void) inst;
_silence_unused(static_cast<U &&>(args)...);
#endif
}
template <class T, class U> static constexpr inline void on_outcome_copy_construction(T *inst, U &&v) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_outcome_copy_construction(inst, static_cast<U &&>(v));
#else
(void) inst;
(void) v;
#endif
}
template <class T, class U> static constexpr inline void on_outcome_move_construction(T *inst, U &&v) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_outcome_move_construction(inst, static_cast<U &&>(v));
#else
(void) inst;
(void) v;
#endif
}
template <class T, class U, class... Args>
static constexpr inline void on_outcome_in_place_construction(T *inst, in_place_type_t<U> _, Args &&... args) noexcept
{
#if OUTCOME_ENABLE_LEGACY_SUPPORT_FOR < 220
using namespace hooks;
hook_outcome_in_place_construction(inst, _, static_cast<Args &&>(args)...);
#else
(void) inst;
(void) _;
_silence_unused(static_cast<Args &&>(args)...);
#endif
}
template <class Impl> static constexpr void narrow_value_check(Impl &&self) noexcept
{
if(!_has_value(self))
{
_make_ub(self);
}
}
template <class Impl> static constexpr void narrow_error_check(Impl &&self) noexcept
{
if(!_has_error(self))
{
_make_ub(self);
}
}
template <class Impl> static constexpr void narrow_exception_check(Impl &&self) noexcept
{
if(!_has_exception(self))
{
_make_ub(self);
}
}
};
} // namespace policy
OUTCOME_V2_NAMESPACE_END
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition all_narrow. Potential doc page: `all_narrow`
*/
struct all_narrow : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self) { base::narrow_value_check(static_cast<Impl &&>(self)); }
template <class Impl> static constexpr void wide_error_check(Impl &&self) { base::narrow_error_check(static_cast<Impl &&>(self)); }
template <class Impl> static constexpr void wide_exception_check(Impl &&self) { base::narrow_exception_check(static_cast<Impl &&>(self)); }
};
} // namespace policy
OUTCOME_V2_NAMESPACE_END
#endif
/* Policies for result and outcome
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (12 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_POLICY_TERMINATE_HPP
#define OUTCOME_POLICY_TERMINATE_HPP
#include <cstdlib>
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition terminate. Potential doc page: `terminate`
*/
struct terminate : base
{
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
std::abort();
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self) noexcept
{
if(!base::_has_error(static_cast<Impl &&>(self)))
{
std::abort();
}
}
template <class Impl> static constexpr void wide_exception_check(Impl &&self)
{
if(!base::_has_exception(static_cast<Impl &&>(self)))
{
std::abort();
}
}
};
} // namespace policy
OUTCOME_V2_NAMESPACE_END
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
template <class R, class S, class NoValuePolicy> //
class basic_result;
namespace detail
{
// These are reused by basic_outcome to save load on the compiler
template <class value_type, class error_type> struct result_predicates
{
// Predicate for the implicit constructors to be available. Weakened to allow result<int, C enum>.
static constexpr bool implicit_constructors_enabled = //
!(trait::is_error_type<std::decay_t<value_type>>::value &&
trait::is_error_type<std::decay_t<error_type>>::value) // both value and error types are not whitelisted error types
&& ((!detail::is_implicitly_constructible<value_type, error_type> &&
!detail::is_implicitly_constructible<error_type, value_type>) // if value and error types cannot be constructed into one another
|| (trait::is_error_type<std::decay_t<error_type>>::value // if error type is a whitelisted error type
&& !detail::is_implicitly_constructible<error_type, value_type> // AND which cannot be constructed from the value type
&& std::is_integral<value_type>::value)); // AND the value type is some integral type
// Predicate for the value converting constructor to be available. Weakened to allow result<int, C enum>.
template <class T>
static constexpr bool enable_value_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
&& ((detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T>) // is unambiguously for value type
|| (std::is_same<value_type, std::decay_t<T>>::value // OR is my value type exactly
&& detail::is_implicitly_constructible<value_type, T>) ); // and my value type is constructible from this ref form of T
// Predicate for the error converting constructor to be available. Weakened to allow result<int, C enum>.
template <class T>
static constexpr bool enable_error_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !trait::is_error_type_enum<error_type, std::decay_t<T>>::value // not an enum valid for my error type
&& ((!detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T>) // is unambiguously for error type
|| (std::is_same<error_type, std::decay_t<T>>::value // OR is my error type exactly
&& detail::is_implicitly_constructible<error_type, T>) ); // and my error type is constructible from this ref form of T
// Predicate for the error condition converting constructor to be available.
template <class ErrorCondEnum>
static constexpr bool enable_error_condition_converting_constructor = //
!is_in_place_type_t<std::decay_t<ErrorCondEnum>>::value // not in place construction
&& trait::is_error_type_enum<error_type, std::decay_t<ErrorCondEnum>>::value // is an error condition enum
/*&& !detail::is_implicitly_constructible<value_type, ErrorCondEnum> && !detail::is_implicitly_constructible<error_type, ErrorCondEnum>*/; // not
// constructible
// via any other
// means
// Predicate for the converting constructor from a compatible input to be available.
template <class T, class U, class V>
static constexpr bool enable_compatible_conversion = //
(std::is_void<T>::value ||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // if our value types are constructible
&&(std::is_void<U>::value ||
detail::is_explicitly_constructible<error_type, typename basic_result<T, U, V>::error_type>) // if our error types are constructible
;
// Predicate for the converting constructor from a make_error_code() of the input to be available.
template <class T, class U, class V>
static constexpr bool enable_make_error_code_compatible_conversion = //
trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
&& !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
&& (std::is_void<T>::value ||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
&&detail::is_explicitly_constructible<error_type,
typename trait::is_error_code_available<U>::type>; // and our error type is constructible from a make_error_code()
// Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
template <class T, class U, class V>
static constexpr bool enable_make_exception_ptr_compatible_conversion = //
trait::is_exception_ptr_available<std::decay_t<error_type>>::value // if error type has an exception ptr
&& !enable_compatible_conversion<T, U, V> // and the normal compatible conversion is not available
&& (std::is_void<T>::value ||
detail::is_explicitly_constructible<value_type, typename basic_result<T, U, V>::value_type>) // and if our value types are constructible
&&detail::is_explicitly_constructible<error_type, typename trait::is_exception_ptr_available<U>::type>; // and our error type is constructible from a
// make_exception_ptr()
// Predicate for the implicit converting inplace constructor from a compatible input to be available.
struct disable_inplace_value_error_constructor;
template <class... Args>
using choose_inplace_value_error_constructor = std::conditional_t< //
detail::is_constructible<value_type, Args...> && detail::is_constructible<error_type, Args...>, //
disable_inplace_value_error_constructor, //
std::conditional_t< //
detail::is_constructible<value_type, Args...>, //
value_type, //
std::conditional_t< //
detail::is_constructible<error_type, Args...>, //
error_type, //
disable_inplace_value_error_constructor>>>;
template <class... Args>
static constexpr bool enable_inplace_value_error_constructor =
implicit_constructors_enabled //
&& !std::is_same<choose_inplace_value_error_constructor<Args...>, disable_inplace_value_error_constructor>::value;
};
template <class T, class U> constexpr inline const U &extract_value_from_success(const success_type<U> &v) { return v.value(); }
template <class T, class U> constexpr inline U &&extract_value_from_success(success_type<U> &&v) { return static_cast<success_type<U> &&>(v).value(); }
template <class T> constexpr inline T extract_value_from_success(const success_type<void> & /*unused*/) { return T{}; }
template <class T, class U, class V> constexpr inline const U &extract_error_from_failure(const failure_type<U, V> &v) { return v.error(); }
template <class T, class U, class V> constexpr inline U &&extract_error_from_failure(failure_type<U, V> &&v)
{
return static_cast<failure_type<U, V> &&>(v).error();
}
template <class T, class V> constexpr inline T extract_error_from_failure(const failure_type<void, V> & /*unused*/) { return T{}; }
template <class T> struct is_basic_result
{
static constexpr bool value = false;
};
template <class R, class S, class T> struct is_basic_result<basic_result<R, S, T>>
{
static constexpr bool value = true;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type alias template <class T> is_basic_result. Potential doc page: `is_basic_result<T>`
*/
template <class T> using is_basic_result = detail::is_basic_result<std::decay_t<T>>;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_basic_result_v = detail::is_basic_result<std::decay_t<T>>::value;
namespace concepts
{
#if defined(__cpp_concepts)
/* The `basic_result` concept.
\requires That `U` matches a `basic_result`.
*/
template <class U>
concept OUTCOME_GCC6_CONCEPT_BOOL basic_result =
OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
(requires(U v) { OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>(v); } && //
detail::convertible<U, OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>> && //
detail::base_of<OUTCOME_V2_NAMESPACE::basic_result<typename U::value_type, typename U::error_type, typename U::no_value_policy_type>, U>);
#else
namespace detail
{
inline no_match match_basic_result(...);
template <class R, class S, class NVP, class T, //
typename = typename T::value_type, //
typename = typename T::error_type, //
typename = typename T::no_value_policy_type, //
typename std::enable_if_t<std::is_convertible<T, OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>>::value && //
std::is_base_of<OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP>, T>::value,
bool> = true>
inline OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> match_basic_result(OUTCOME_V2_NAMESPACE::basic_result<R, S, NVP> &&, T &&);
template <class U>
static constexpr bool basic_result = OUTCOME_V2_NAMESPACE::is_basic_result<U>::value ||
!std::is_same<no_match, decltype(match_basic_result(std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>(),
std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
} // namespace detail
/* The `basic_result` concept.
\requires That `U` matches a `basic_result`.
*/
template <class U> static constexpr bool basic_result = detail::basic_result<U>;
#endif
} // namespace concepts
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
namespace hooks
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class NoValuePolicy> constexpr inline uint16_t spare_storage(const detail::basic_result_storage<R, S, NoValuePolicy> *r) noexcept
{
return r->_state._status.spare_storage_value;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class NoValuePolicy>
constexpr inline void set_spare_storage(detail::basic_result_storage<R, S, NoValuePolicy> *r, uint16_t v) noexcept
{
r->_state._status.spare_storage_value = v;
}
} // namespace hooks
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class R, class S, class NoValuePolicy> basic_result. Potential doc page: `basic_result<T, E, NoValuePolicy>`
*/
template <class R, class S, class NoValuePolicy> //
class OUTCOME_NODISCARD basic_result : public detail::basic_result_final<R, S, NoValuePolicy>
{
static_assert(trait::type_can_be_used_in_basic_result<R>, "The type R cannot be used in a basic_result");
static_assert(trait::type_can_be_used_in_basic_result<S>, "The type S cannot be used in a basic_result");
using base = detail::basic_result_final<R, S, NoValuePolicy>;
struct implicit_constructors_disabled_tag
{
};
struct value_converting_constructor_tag
{
};
struct error_converting_constructor_tag
{
};
struct error_condition_converting_constructor_tag
{
};
struct explicit_valueornone_converting_constructor_tag
{
};
struct explicit_valueorerror_converting_constructor_tag
{
};
struct explicit_compatible_copy_conversion_tag
{
};
struct explicit_compatible_move_conversion_tag
{
};
struct explicit_make_error_code_compatible_copy_conversion_tag
{
};
struct explicit_make_error_code_compatible_move_conversion_tag
{
};
struct explicit_make_exception_ptr_compatible_copy_conversion_tag
{
};
struct explicit_make_exception_ptr_compatible_move_conversion_tag
{
};
public:
using value_type = R;
using error_type = S;
using no_value_policy_type = NoValuePolicy;
using value_type_if_enabled = typename base::_value_type;
using error_type_if_enabled = typename base::_error_type;
template <class T, class U = S, class V = NoValuePolicy> using rebind = basic_result<T, U, V>;
public:
// Requirement predicates for result.
struct predicate
{
using base = detail::result_predicates<value_type, error_type>;
// Predicate for any constructors to be available at all
static constexpr bool constructors_enabled = !std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value;
// Predicate for implicit constructors to be available at all
static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
// Predicate for the value converting constructor to be available.
template <class T>
static constexpr bool enable_value_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_result>::value // not my type
&& base::template enable_value_converting_constructor<T>;
// Predicate for the error converting constructor to be available.
template <class T>
static constexpr bool enable_error_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_result>::value // not my type
&& base::template enable_error_converting_constructor<T>;
// Predicate for the error condition converting constructor to be available.
template <class ErrorCondEnum>
static constexpr bool enable_error_condition_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<ErrorCondEnum>, basic_result>::value // not my type
&& base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
// Predicate for the converting constructor from a compatible input to be available.
template <class T, class U, class V>
static constexpr bool enable_compatible_conversion = //
constructors_enabled //
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
&& base::template enable_compatible_conversion<T, U, V>;
// Predicate for the converting constructor from a make_error_code() of the input to be available.
template <class T, class U, class V>
static constexpr bool enable_make_error_code_compatible_conversion = //
constructors_enabled //
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
&& base::template enable_make_error_code_compatible_conversion<T, U, V>;
// Predicate for the converting constructor from a make_exception_ptr() of the input to be available.
template <class T, class U, class V>
static constexpr bool enable_make_exception_ptr_compatible_conversion = //
constructors_enabled //
&& !std::is_same<basic_result<T, U, V>, basic_result>::value // not my type
&& base::template enable_make_exception_ptr_compatible_conversion<T, U, V>;
// Predicate for the inplace construction of value to be available.
template <class... Args>
static constexpr bool enable_inplace_value_constructor = //
constructors_enabled //
&& (std::is_void<value_type>::value //
|| detail::is_constructible<value_type, Args...>);
// Predicate for the inplace construction of error to be available.
template <class... Args>
static constexpr bool enable_inplace_error_constructor = //
constructors_enabled //
&& (std::is_void<error_type>::value //
|| detail::is_constructible<error_type, Args...>);
// Predicate for the implicit converting inplace constructor to be available.
template <class... Args>
static constexpr bool enable_inplace_value_error_constructor = //
constructors_enabled //
&&base::template enable_inplace_value_error_constructor<Args...>;
template <class... Args> using choose_inplace_value_error_constructor = typename base::template choose_inplace_value_error_constructor<Args...>;
};
public:
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result() = delete;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result(basic_result && /*unused*/) = default; // NOLINT
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result(const basic_result & /*unused*/) = default;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result &operator=(basic_result && /*unused*/) = default; // NOLINT
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
basic_result &operator=(const basic_result & /*unused*/) = default;
~basic_result() = default;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class Arg, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!predicate::constructors_enabled && (sizeof...(Args) >= 0)))
basic_result(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_result<T, T> is NOT SUPPORTED, see docs!
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
&& (detail::is_implicitly_constructible<value_type, T> || detail::is_implicitly_constructible<error_type, T>) )))
basic_result(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) =
delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
constexpr basic_result(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<typename base::value_type>, static_cast<T &&>(t)}
{
no_value_policy_type::on_result_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
constexpr basic_result(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<typename base::error_type>, static_cast<T &&>(t)}
{
no_value_policy_type::on_result_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
constexpr basic_result(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(
noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
: base{in_place_type<typename base::error_type>, make_error_code(t)}
{
no_value_policy_type::on_result_construction(this, static_cast<ErrorCondEnum &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(convert::value_or_error<basic_result, std::decay_t<T>>::enable_result_inputs || !concepts::basic_result<T>), //
OUTCOME_TEXPR(convert::value_or_error<basic_result, std::decay_t<T>>{}(std::declval<T>())))
constexpr explicit basic_result(T &&o,
explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
: basic_result{convert::value_or_error<basic_result, std::decay_t<T>>{}(static_cast<T &&>(o))}
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
constexpr explicit basic_result(
const basic_result<T, U, V> &o,
explicit_compatible_copy_conversion_tag /*unused*/ =
explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
: base{typename base::compatible_conversion_tag(), o}
{
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V>))
constexpr explicit basic_result(
basic_result<T, U, V> &&o,
explicit_compatible_move_conversion_tag /*unused*/ =
explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>)
: base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
{
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
constexpr explicit basic_result(const basic_result<T, U, V> &o,
explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_error_code(std::declval<U>())))
: base{typename base::make_error_code_compatible_conversion_tag(), o}
{
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<T, U, V>))
constexpr explicit basic_result(basic_result<T, U, V> &&o,
explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_error_code(std::declval<U>())))
: base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
{
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
constexpr explicit basic_result(const basic_result<T, U, V> &o,
explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_exception_ptr(std::declval<U>())))
: base{typename base::make_exception_ptr_compatible_conversion_tag(), o}
{
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<T, U, V>))
constexpr explicit basic_result(basic_result<T, U, V> &&o,
explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_exception_ptr(std::declval<U>())))
: base{typename base::make_exception_ptr_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
{
no_value_policy_type::on_result_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, Args...>)
: base{_, static_cast<Args &&>(args)...}
{
no_value_policy_type::on_result_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class U, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<std::initializer_list<U>, Args...>))
constexpr explicit basic_result(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>)
: base{_, il, static_cast<Args &&>(args)...}
{
no_value_policy_type::on_result_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<Args...>))
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, Args...>)
: base{_, static_cast<Args &&>(args)...}
{
no_value_policy_type::on_result_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class U, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<std::initializer_list<U>, Args...>))
constexpr explicit basic_result(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>)
: base{_, il, static_cast<Args &&>(args)...}
{
no_value_policy_type::on_result_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class A1, class A2, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_error_constructor<A1, A2, Args...>))
constexpr basic_result(A1 &&a1, A2 &&a2, Args &&... args) noexcept(noexcept(
typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(), std::declval<Args>()...)))
: basic_result(in_place_type<typename predicate::template choose_inplace_value_error_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1),
static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
constexpr basic_result(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
: base{in_place_type<value_type_if_enabled>}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, void, void>))
constexpr basic_result(const success_type<T> &o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(o)}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void>))
constexpr basic_result(success_type<T> &&o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<value_type_if_enabled>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_move_construction(this, static_cast<success_type<T> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
constexpr basic_result(const failure_type<T> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(o)}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<void, T, void>))
constexpr basic_result(failure_type<T> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<error_type_if_enabled>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
constexpr basic_result(const failure_type<T> &o,
explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
: base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_error_code_compatible_conversion<void, T, void>))
constexpr basic_result(failure_type<T> &&o,
explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
: base{in_place_type<error_type_if_enabled>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
constexpr basic_result(const failure_type<T> &o,
explicit_make_exception_ptr_compatible_copy_conversion_tag /*unused*/ =
explicit_make_exception_ptr_compatible_copy_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
: base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(o))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_make_exception_ptr_compatible_conversion<void, T, void>))
constexpr basic_result(failure_type<T> &&o,
explicit_make_exception_ptr_compatible_move_conversion_tag /*unused*/ =
explicit_make_exception_ptr_compatible_move_conversion_tag()) noexcept(noexcept(make_exception_ptr(std::declval<T>()))) // NOLINT
: base{in_place_type<error_type_if_enabled>, make_exception_ptr(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_result_move_construction(this, static_cast<failure_type<T> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
constexpr void swap(basic_result &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
&& (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value))
{
this->_state.swap(o._state);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
auto as_failure() const & { return failure(this->assume_error(), hooks::spare_storage(this)); }
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
auto as_failure() &&
{
this->_state._status.set_have_moved_from(true);
return failure(static_cast<basic_result &&>(*this).assume_error(), hooks::spare_storage(this));
}
#ifdef __APPLE__
failure_type<error_type> _xcode_workaround_as_failure() &&;
#endif
};
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P> inline void swap(basic_result<R, S, P> &a, basic_result<R, S, P> &b) noexcept(noexcept(a.swap(b)))
{
a.swap(b);
}
#if !defined(NDEBUG)
// Check is trivial in all ways except default constructibility
// static_assert(std::is_trivial<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivial!");
// static_assert(std::is_trivially_default_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially default
// constructible!");
static_assert(std::is_trivially_copyable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copyable!");
static_assert(std::is_trivially_assignable<basic_result<int, long, policy::all_narrow>, basic_result<int, long, policy::all_narrow>>::value,
"result<int> is not trivially assignable!");
static_assert(std::is_trivially_destructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy constructible!");
static_assert(std::is_trivially_move_constructible<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move constructible!");
static_assert(std::is_trivially_copy_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not trivially move assignable!");
// Also check is standard layout
static_assert(std::is_standard_layout<basic_result<int, long, policy::all_narrow>>::value, "result<int> is not a standard layout type!");
#endif
OUTCOME_V2_NAMESPACE_END
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif
/* Exception observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_HPP
#define OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
template <class Base, class R, class S, class P, class NoValuePolicy> class basic_outcome_exception_observers : public Base
{
public:
using exception_type = P;
using Base::Base;
constexpr inline exception_type &assume_exception() & noexcept;
constexpr inline const exception_type &assume_exception() const &noexcept;
constexpr inline exception_type &&assume_exception() && noexcept;
constexpr inline const exception_type &&assume_exception() const &&noexcept;
constexpr inline exception_type &exception() &;
constexpr inline const exception_type &exception() const &;
constexpr inline exception_type &&exception() &&;
constexpr inline const exception_type &&exception() const &&;
};
// Exception observers not present
template <class Base, class R, class S, class NoValuePolicy> class basic_outcome_exception_observers<Base, R, S, void, NoValuePolicy> : public Base
{
public:
using Base::Base;
constexpr void assume_exception() const noexcept { NoValuePolicy::narrow_exception_check(this); }
constexpr void exception() const { NoValuePolicy::wide_exception_check(this); }
};
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
/* Failure observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_OUTCOME_FAILURE_OBSERVERS_HPP
#define OUTCOME_BASIC_OUTCOME_FAILURE_OBSERVERS_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace detail
{
namespace adl
{
struct search_detail_adl
{
};
// Do NOT use template requirements here!
template <class S, typename = decltype(basic_outcome_failure_exception_from_error(std::declval<S>()))>
inline auto _delayed_lookup_basic_outcome_failure_exception_from_error(const S &ec, search_detail_adl /*unused*/)
{
// ADL discovered
return basic_outcome_failure_exception_from_error(ec);
}
} // namespace adl
#if defined(_MSC_VER) && _MSC_VER <= 1923 // VS2019
// VS2017 and VS2019 with /permissive- chokes on the correct form due to over eager early instantiation.
template <class S, class P> inline void _delayed_lookup_basic_outcome_failure_exception_from_error(...) { static_assert(sizeof(S) == 0, "No specialisation for these error and exception types available!"); }
#else
template <class S, class P> inline void _delayed_lookup_basic_outcome_failure_exception_from_error(...) = delete; // NOLINT No specialisation for these error and exception types available!
#endif
template <class exception_type> inline exception_type current_exception_or_fatal(std::exception_ptr e) { std::rethrow_exception(e); }
template <> inline std::exception_ptr current_exception_or_fatal<std::exception_ptr>(std::exception_ptr e) { return e; }
template <class Base, class R, class S, class P, class NoValuePolicy> class basic_outcome_failure_observers : public Base
{
public:
using exception_type = P;
using Base::Base;
exception_type failure() const noexcept
{
#ifdef __cpp_exceptions
try
#endif
{
if(this->_state._status.have_exception())
{
return this->assume_exception();
}
if(this->_state._status.have_error())
{
return _delayed_lookup_basic_outcome_failure_exception_from_error(this->assume_error(), adl::search_detail_adl());
}
return exception_type();
}
#ifdef __cpp_exceptions
catch(...)
{
// Return the failure if exception_type is std::exception_ptr,
// otherwise terminate same as throwing an exception inside noexcept
return current_exception_or_fatal<exception_type>(std::current_exception());
}
#endif
}
};
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation" // Standardese markup confuses clang
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
template <class R, class S, class P, class NoValuePolicy> //
class basic_outcome;
namespace detail
{
// May be reused by basic_outcome subclasses to save load on the compiler
template <class value_type, class error_type, class exception_type> struct outcome_predicates
{
using result = result_predicates<value_type, error_type>;
// Predicate for the implicit constructors to be available
static constexpr bool implicit_constructors_enabled = //
result::implicit_constructors_enabled //
&& !detail::is_implicitly_constructible<value_type, exception_type> //
&& !detail::is_implicitly_constructible<error_type, exception_type> //
&& !detail::is_implicitly_constructible<exception_type, value_type> //
&& !detail::is_implicitly_constructible<exception_type, error_type>;
// Predicate for the value converting constructor to be available.
template <class T>
static constexpr bool enable_value_converting_constructor = //
implicit_constructors_enabled //
&&result::template enable_value_converting_constructor<T> //
&& !detail::is_implicitly_constructible<exception_type, T>; // deliberately less tolerant of ambiguity than result's edition
// Predicate for the error converting constructor to be available.
template <class T>
static constexpr bool enable_error_converting_constructor = //
implicit_constructors_enabled //
&&result::template enable_error_converting_constructor<T> //
&& !detail::is_implicitly_constructible<exception_type, T>; // deliberately less tolerant of ambiguity than result's edition
// Predicate for the error condition converting constructor to be available.
template <class ErrorCondEnum>
static constexpr bool enable_error_condition_converting_constructor = result::template enable_error_condition_converting_constructor<ErrorCondEnum> //
&& !detail::is_implicitly_constructible<exception_type, ErrorCondEnum>;
// Predicate for the exception converting constructor to be available.
template <class T>
static constexpr bool enable_exception_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !detail::is_implicitly_constructible<value_type, T> && !detail::is_implicitly_constructible<error_type, T> &&
detail::is_implicitly_constructible<exception_type, T>;
// Predicate for the error + exception converting constructor to be available.
template <class T, class U>
static constexpr bool enable_error_exception_converting_constructor = //
implicit_constructors_enabled //
&& !is_in_place_type_t<std::decay_t<T>>::value // not in place construction
&& !detail::is_implicitly_constructible<value_type, T> && detail::is_implicitly_constructible<error_type, T> //
&& !detail::is_implicitly_constructible<value_type, U> && detail::is_implicitly_constructible<exception_type, U>;
// Predicate for the converting copy constructor from a compatible outcome to be available.
template <class T, class U, class V, class W>
static constexpr bool enable_compatible_conversion = //
(std::is_void<T>::value ||
detail::is_explicitly_constructible<value_type, typename basic_outcome<T, U, V, W>::value_type>) // if our value types are constructible
&&(std::is_void<U>::value ||
detail::is_explicitly_constructible<error_type, typename basic_outcome<T, U, V, W>::error_type>) // if our error types are constructible
&&(std::is_void<V>::value ||
detail::is_explicitly_constructible<exception_type, typename basic_outcome<T, U, V, W>::exception_type>) // if our exception types are constructible
;
// Predicate for the converting constructor from a make_error_code() of the input to be available.
template <class T, class U, class V, class W>
static constexpr bool enable_make_error_code_compatible_conversion = //
trait::is_error_code_available<std::decay_t<error_type>>::value // if error type has an error code
&& !enable_compatible_conversion<T, U, V, W> // and the normal compatible conversion is not available
&& (std::is_void<T>::value ||
detail::is_explicitly_constructible<value_type, typename basic_outcome<T, U, V, W>::value_type>) // and if our value types are constructible
&&detail::is_explicitly_constructible<error_type,
typename trait::is_error_code_available<U>::type> // and our error type is constructible from a make_error_code()
&& (std::is_void<V>::value ||
detail::is_explicitly_constructible<exception_type, typename basic_outcome<T, U, V, W>::exception_type>); // and our exception types are constructible
// Predicate for the implicit converting inplace constructor from a compatible input to be available.
struct disable_inplace_value_error_exception_constructor;
template <class... Args>
using choose_inplace_value_error_exception_constructor = std::conditional_t< //
((static_cast<int>(detail::is_constructible<value_type, Args...>) + static_cast<int>(detail::is_constructible<error_type, Args...>) +
static_cast<int>(detail::is_constructible<exception_type, Args...>)) > 1), //
disable_inplace_value_error_exception_constructor, //
std::conditional_t< //
detail::is_constructible<value_type, Args...>, //
value_type, //
std::conditional_t< //
detail::is_constructible<error_type, Args...>, //
error_type, //
std::conditional_t< //
detail::is_constructible<exception_type, Args...>, //
exception_type, //
disable_inplace_value_error_exception_constructor>>>>;
template <class... Args>
static constexpr bool enable_inplace_value_error_exception_constructor = //
implicit_constructors_enabled &&
!std::is_same<choose_inplace_value_error_exception_constructor<Args...>, disable_inplace_value_error_exception_constructor>::value;
};
// Select whether to use basic_outcome_failure_observers or not
template <class Base, class R, class S, class P, class NoValuePolicy>
using select_basic_outcome_failure_observers = //
std::conditional_t<trait::is_error_code_available<S>::value && trait::is_exception_ptr_available<P>::value,
basic_outcome_failure_observers<Base, R, S, P, NoValuePolicy>, Base>;
template <class T, class U, class V> constexpr inline const V &extract_exception_from_failure(const failure_type<U, V> &v) { return v.exception(); }
template <class T, class U, class V> constexpr inline V &&extract_exception_from_failure(failure_type<U, V> &&v)
{
return static_cast<failure_type<U, V> &&>(v).exception();
}
template <class T, class U> constexpr inline const U &extract_exception_from_failure(const failure_type<U, void> &v) { return v.error(); }
template <class T, class U> constexpr inline U &&extract_exception_from_failure(failure_type<U, void> &&v)
{
return static_cast<failure_type<U, void> &&>(v).error();
}
template <class T> struct is_basic_outcome
{
static constexpr bool value = false;
};
template <class R, class S, class T, class N> struct is_basic_outcome<basic_outcome<R, S, T, N>>
{
static constexpr bool value = true;
};
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
type alias template <class T> is_basic_outcome. Potential doc page: `is_basic_outcome<T>`
*/
template <class T> using is_basic_outcome = detail::is_basic_outcome<std::decay_t<T>>;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> static constexpr bool is_basic_outcome_v = detail::is_basic_outcome<std::decay_t<T>>::value;
namespace concepts
{
#if defined(__cpp_concepts)
/* The `basic_outcome` concept.
\requires That `U` matches a `basic_outcome`.
*/
template <class U>
concept OUTCOME_GCC6_CONCEPT_BOOL basic_outcome =
OUTCOME_V2_NAMESPACE::is_basic_outcome<U>::value ||
(requires(U v) {
OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>(v);
} && //
detail::convertible<
U, OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>> && //
detail::base_of<
OUTCOME_V2_NAMESPACE::basic_outcome<typename U::value_type, typename U::error_type, typename U::exception_type, typename U::no_value_policy_type>, U>);
#else
namespace detail
{
inline no_match match_basic_outcome(...);
template <class R, class S, class P, class NVP, class T, //
typename = typename T::value_type, //
typename = typename T::error_type, //
typename = typename T::exception_type, //
typename = typename T::no_value_policy_type, //
typename std::enable_if_t<std::is_convertible<T, OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP>>::value && //
std::is_base_of<OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP>, T>::value,
bool> = true>
inline OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP> match_basic_outcome(OUTCOME_V2_NAMESPACE::basic_outcome<R, S, P, NVP> &&, T &&);
template <class U>
static constexpr bool basic_outcome =
OUTCOME_V2_NAMESPACE::is_basic_outcome<U>::value ||
!std::is_same<no_match, decltype(match_basic_outcome(std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>(),
std::declval<OUTCOME_V2_NAMESPACE::detail::devoid<U>>()))>::value;
} // namespace detail
/* The `basic_outcome` concept.
\requires That `U` matches a `basic_outcome`.
*/
template <class U> static constexpr bool basic_outcome = detail::basic_outcome<U>;
#endif
} // namespace concepts
namespace hooks
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P, class NoValuePolicy, class U>
constexpr inline void override_outcome_exception(basic_outcome<R, S, P, NoValuePolicy> *o, U &&v) noexcept;
} // namespace hooks
/*! AWAITING HUGO JSON CONVERSION TOOL
type definition template <class R, class S, class P, class NoValuePolicy> basic_outcome. Potential doc page: `basic_outcome<T, EC, EP, NoValuePolicy>`
*/
template <class R, class S, class P, class NoValuePolicy> //
class OUTCOME_NODISCARD basic_outcome
: public detail::select_basic_outcome_failure_observers<
detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>
{
static_assert(trait::type_can_be_used_in_basic_result<P>, "The exception_type cannot be used");
static_assert(std::is_void<P>::value || std::is_default_constructible<P>::value, "exception_type must be void or default constructible");
using base = detail::select_basic_outcome_failure_observers<
detail::basic_outcome_exception_observers<detail::basic_result_final<R, S, NoValuePolicy>, R, S, P, NoValuePolicy>, R, S, P, NoValuePolicy>;
friend struct policy::base;
template <class T, class U, class V, class W> //
friend class basic_outcome;
template <class T, class U, class V, class W, class X>
friend constexpr inline void hooks::override_outcome_exception(basic_outcome<T, U, V, W> *o, X &&v) noexcept; // NOLINT
struct implicit_constructors_disabled_tag
{
};
struct value_converting_constructor_tag
{
};
struct error_converting_constructor_tag
{
};
struct error_condition_converting_constructor_tag
{
};
struct exception_converting_constructor_tag
{
};
struct error_exception_converting_constructor_tag
{
};
struct explicit_valueorerror_converting_constructor_tag
{
};
struct explicit_compatible_copy_conversion_tag
{
};
struct explicit_compatible_move_conversion_tag
{
};
struct explicit_make_error_code_compatible_copy_conversion_tag
{
};
struct explicit_make_error_code_compatible_move_conversion_tag
{
};
struct error_failure_tag
{
};
struct exception_failure_tag
{
};
struct disable_in_place_value_type
{
};
struct disable_in_place_error_type
{
};
struct disable_in_place_exception_type
{
};
public:
using value_type = R;
using error_type = S;
using exception_type = P;
using no_value_policy_type = NoValuePolicy;
template <class T, class U = S, class V = P, class W = NoValuePolicy> using rebind = basic_outcome<T, U, V, W>;
protected:
// Requirement predicates for outcome.
struct predicate
{
using base = detail::outcome_predicates<value_type, error_type, exception_type>;
// Predicate for any constructors to be available at all
static constexpr bool constructors_enabled =
(!std::is_same<std::decay_t<value_type>, std::decay_t<error_type>>::value || (std::is_void<value_type>::value && std::is_void<error_type>::value)) //
&& (!std::is_same<std::decay_t<value_type>, std::decay_t<exception_type>>::value ||
(std::is_void<value_type>::value && std::is_void<exception_type>::value)) //
&& (!std::is_same<std::decay_t<error_type>, std::decay_t<exception_type>>::value ||
(std::is_void<error_type>::value && std::is_void<exception_type>::value)) //
;
// Predicate for implicit constructors to be available at all
static constexpr bool implicit_constructors_enabled = constructors_enabled && base::implicit_constructors_enabled;
// Predicate for the value converting constructor to be available.
template <class T>
static constexpr bool enable_value_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
&& base::template enable_value_converting_constructor<T>;
// Predicate for the error converting constructor to be available.
template <class T>
static constexpr bool enable_error_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
&& base::template enable_error_converting_constructor<T>;
// Predicate for the error condition converting constructor to be available.
template <class ErrorCondEnum>
static constexpr bool enable_error_condition_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<ErrorCondEnum>, basic_outcome>::value // not my type
&& base::template enable_error_condition_converting_constructor<ErrorCondEnum>;
// Predicate for the exception converting constructor to be available.
template <class T>
static constexpr bool enable_exception_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
&& base::template enable_exception_converting_constructor<T>;
// Predicate for the error + exception converting constructor to be available.
template <class T, class U>
static constexpr bool enable_error_exception_converting_constructor = //
constructors_enabled //
&& !std::is_same<std::decay_t<T>, basic_outcome>::value // not my type
&& base::template enable_error_exception_converting_constructor<T, U>;
// Predicate for the converting constructor from a compatible input to be available.
template <class T, class U, class V, class W>
static constexpr bool enable_compatible_conversion = //
constructors_enabled //
&& !std::is_same<basic_outcome<T, U, V, W>, basic_outcome>::value // not my type
&& base::template enable_compatible_conversion<T, U, V, W>;
// Predicate for the converting constructor from a make_error_code() of the input to be available.
template <class T, class U, class V, class W>
static constexpr bool enable_make_error_code_compatible_conversion = //
constructors_enabled //
&& !std::is_same<basic_outcome<T, U, V, W>, basic_outcome>::value // not my type
&& base::template enable_make_error_code_compatible_conversion<T, U, V, W>;
// Predicate for the inplace construction of value to be available.
template <class... Args>
static constexpr bool enable_inplace_value_constructor = //
constructors_enabled //
&& (std::is_void<value_type>::value //
|| detail::is_constructible<value_type, Args...>);
// Predicate for the inplace construction of error to be available.
template <class... Args>
static constexpr bool enable_inplace_error_constructor = //
constructors_enabled //
&& (std::is_void<error_type>::value //
|| detail::is_constructible<error_type, Args...>);
// Predicate for the inplace construction of exception to be available.
template <class... Args>
static constexpr bool enable_inplace_exception_constructor = //
constructors_enabled //
&& (std::is_void<exception_type>::value //
|| detail::is_constructible<exception_type, Args...>);
// Predicate for the implicit converting inplace constructor to be available.
template <class... Args>
static constexpr bool enable_inplace_value_error_exception_constructor = //
constructors_enabled //
&&base::template enable_inplace_value_error_exception_constructor<Args...>;
template <class... Args>
using choose_inplace_value_error_exception_constructor = typename base::template choose_inplace_value_error_exception_constructor<Args...>;
};
public:
using value_type_if_enabled =
std::conditional_t<std::is_same<value_type, error_type>::value || std::is_same<value_type, exception_type>::value, disable_in_place_value_type, value_type>;
using error_type_if_enabled =
std::conditional_t<std::is_same<error_type, value_type>::value || std::is_same<error_type, exception_type>::value, disable_in_place_error_type, error_type>;
using exception_type_if_enabled = std::conditional_t<std::is_same<exception_type, value_type>::value || std::is_same<exception_type, error_type>::value,
disable_in_place_exception_type, exception_type>;
protected:
detail::devoid<exception_type> _ptr;
public:
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class Arg, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED((!predicate::constructors_enabled && sizeof...(Args) >= 0)))
basic_outcome(Arg && /*unused*/, Args &&... /*unused*/) = delete; // NOLINT basic_outcome<> with any of the same type is NOT SUPPORTED, see docs!
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED((predicate::constructors_enabled && !predicate::implicit_constructors_enabled //
&& (detail::is_implicitly_constructible<value_type, T> || detail::is_implicitly_constructible<error_type, T> ||
detail::is_implicitly_constructible<exception_type, T>) )))
basic_outcome(T && /*unused*/, implicit_constructors_disabled_tag /*unused*/ = implicit_constructors_disabled_tag()) =
delete; // NOLINT Implicit constructors disabled, use explicit in_place_type<T>, success() or failure(). see docs!
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_value_converting_constructor<T>))
constexpr basic_outcome(T &&t, value_converting_constructor_tag /*unused*/ = value_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<typename base::_value_type>, static_cast<T &&>(t)}
, _ptr()
{
no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_error_converting_constructor<T>))
constexpr basic_outcome(T &&t, error_converting_constructor_tag /*unused*/ = error_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<typename base::_error_type>, static_cast<T &&>(t)}
, _ptr()
{
no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class ErrorCondEnum)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(error_type(make_error_code(ErrorCondEnum()))), //
OUTCOME_TPRED(predicate::template enable_error_condition_converting_constructor<ErrorCondEnum>))
constexpr basic_outcome(ErrorCondEnum &&t, error_condition_converting_constructor_tag /*unused*/ = error_condition_converting_constructor_tag()) noexcept(
noexcept(error_type(make_error_code(static_cast<ErrorCondEnum &&>(t))))) // NOLINT
: base{in_place_type<typename base::_error_type>, make_error_code(t)}
{
no_value_policy_type::on_outcome_construction(this, static_cast<ErrorCondEnum &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_exception_converting_constructor<T>))
constexpr basic_outcome(T &&t, exception_converting_constructor_tag /*unused*/ = exception_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<exception_type, T>) // NOLINT
: base()
, _ptr(static_cast<T &&>(t))
{
this->_state._status.set_have_exception(true);
no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(t));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_error_exception_converting_constructor<T, U>))
constexpr basic_outcome(T &&a, U &&b, error_exception_converting_constructor_tag /*unused*/ = error_exception_converting_constructor_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T> &&detail::is_nothrow_constructible<exception_type, U>) // NOLINT
: base{in_place_type<typename base::_error_type>, static_cast<T &&>(a)}
, _ptr(static_cast<U &&>(b))
{
this->_state._status.set_have_exception(true);
no_value_policy_type::on_outcome_construction(this, static_cast<T &&>(a), static_cast<U &&>(b));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(convert::value_or_error<basic_outcome, std::decay_t<T>>::enable_result_inputs || !concepts::basic_result<T>), //
OUTCOME_TPRED(convert::value_or_error<basic_outcome, std::decay_t<T>>::enable_outcome_inputs || !concepts::basic_outcome<T>), //
OUTCOME_TEXPR(convert::value_or_error<basic_outcome, std::decay_t<T>>{}(std::declval<T>())))
constexpr explicit basic_outcome(T &&o,
explicit_valueorerror_converting_constructor_tag /*unused*/ = explicit_valueorerror_converting_constructor_tag()) // NOLINT
: basic_outcome{convert::value_or_error<basic_outcome, std::decay_t<T>>{}(static_cast<T &&>(o))}
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, class W)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V, W>))
constexpr explicit basic_outcome(
const basic_outcome<T, U, V, W> &o,
explicit_compatible_copy_conversion_tag /*unused*/ =
explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>
&&detail::is_nothrow_constructible<exception_type, V>)
: base{typename base::compatible_conversion_tag(), o}
, _ptr(o._ptr)
{
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, class W)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_compatible_conversion<T, U, V, W>))
constexpr explicit basic_outcome(
basic_outcome<T, U, V, W> &&o,
explicit_compatible_move_conversion_tag /*unused*/ =
explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>
&&detail::is_nothrow_constructible<exception_type, V>)
: base{typename base::compatible_conversion_tag(), static_cast<basic_outcome<T, U, V, W> &&>(o)}
, _ptr(static_cast<typename basic_outcome<T, U, V, W>::exception_type &&>(o._ptr))
{
no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_outcome<T, U, V, W> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_compatible_conversion<T, U, V>))
constexpr explicit basic_outcome(
const basic_result<T, U, V> &o,
explicit_compatible_copy_conversion_tag /*unused*/ =
explicit_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>
&&detail::is_nothrow_constructible<exception_type>)
: base{typename base::compatible_conversion_tag(), o}
, _ptr()
{
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_compatible_conversion<T, U, V>))
constexpr explicit basic_outcome(
basic_result<T, U, V> &&o,
explicit_compatible_move_conversion_tag /*unused*/ =
explicit_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T> &&detail::is_nothrow_constructible<error_type, U>
&&detail::is_nothrow_constructible<exception_type>)
: base{typename base::compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
, _ptr()
{
no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_make_error_code_compatible_conversion<T, U, V>))
constexpr explicit basic_outcome(const basic_result<T, U, V> &o,
explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_error_code(std::declval<U>())) &&
detail::is_nothrow_constructible<exception_type>)
: base{typename base::make_error_code_compatible_conversion_tag(), o}
, _ptr()
{
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::result_predicates<value_type, error_type>::template enable_make_error_code_compatible_conversion<T, U, V>))
constexpr explicit basic_outcome(basic_result<T, U, V> &&o,
explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_move_conversion_tag()) noexcept(detail::is_nothrow_constructible<value_type, T>
&&noexcept(make_error_code(std::declval<U>())) &&
detail::is_nothrow_constructible<exception_type>)
: base{typename base::make_error_code_compatible_conversion_tag(), static_cast<basic_result<T, U, V> &&>(o)}
, _ptr()
{
no_value_policy_type::on_outcome_move_construction(this, static_cast<basic_result<T, U, V> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<Args...>))
constexpr explicit basic_outcome(in_place_type_t<value_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, Args...>)
: base{_, static_cast<Args &&>(args)...}
, _ptr()
{
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<value_type>, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class U, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_constructor<std::initializer_list<U>, Args...>))
constexpr explicit basic_outcome(in_place_type_t<value_type_if_enabled> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<value_type, std::initializer_list<U>, Args...>)
: base{_, il, static_cast<Args &&>(args)...}
, _ptr()
{
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<value_type>, il, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<Args...>))
constexpr explicit basic_outcome(in_place_type_t<error_type_if_enabled> _, Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, Args...>)
: base{_, static_cast<Args &&>(args)...}
, _ptr()
{
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<error_type>, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class U, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_error_constructor<std::initializer_list<U>, Args...>))
constexpr explicit basic_outcome(in_place_type_t<error_type_if_enabled> _, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<error_type, std::initializer_list<U>, Args...>)
: base{_, il, static_cast<Args &&>(args)...}
, _ptr()
{
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<error_type>, il, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor<Args...>))
constexpr explicit basic_outcome(in_place_type_t<exception_type_if_enabled> /*unused*/,
Args &&... args) noexcept(detail::is_nothrow_constructible<exception_type, Args...>)
: base()
, _ptr(static_cast<Args &&>(args)...)
{
this->_state._status.set_have_exception(true);
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<exception_type>, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class U, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_exception_constructor<std::initializer_list<U>, Args...>))
constexpr explicit basic_outcome(in_place_type_t<exception_type_if_enabled> /*unused*/, std::initializer_list<U> il,
Args &&... args) noexcept(detail::is_nothrow_constructible<exception_type, std::initializer_list<U>, Args...>)
: base()
, _ptr(il, static_cast<Args &&>(args)...)
{
this->_state._status.set_have_exception(true);
no_value_policy_type::on_outcome_in_place_construction(this, in_place_type<exception_type>, il, static_cast<Args &&>(args)...);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class A1, class A2, class... Args)
OUTCOME_TREQUIRES(OUTCOME_TPRED(predicate::template enable_inplace_value_error_exception_constructor<A1, A2, Args...>))
constexpr basic_outcome(A1 &&a1, A2 &&a2, Args &&... args) noexcept(
noexcept(typename predicate::template choose_inplace_value_error_exception_constructor<A1, A2, Args...>(std::declval<A1>(), std::declval<A2>(),
std::declval<Args>()...)))
: basic_outcome(in_place_type<typename predicate::template choose_inplace_value_error_exception_constructor<A1, A2, Args...>>, static_cast<A1 &&>(a1),
static_cast<A2 &&>(a2), static_cast<Args &&>(args)...)
{
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
constexpr basic_outcome(const success_type<void> &o) noexcept(std::is_nothrow_default_constructible<value_type>::value) // NOLINT
: base{in_place_type<typename base::_value_type>}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
constexpr basic_outcome(const success_type<T> &o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(o)}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<T, void, void, void>))
constexpr basic_outcome(success_type<T> &&o) noexcept(detail::is_nothrow_constructible<value_type, T>) // NOLINT
: base{in_place_type<typename base::_value_type>, detail::extract_value_from_success<value_type>(static_cast<success_type<T> &&>(o))}
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_move_construction(this, static_cast<success_type<T> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(const failure_type<T> &o,
error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
, _ptr()
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
constexpr basic_outcome(const failure_type<T> &o,
exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible<exception_type, T>) // NOLINT
: base()
, _ptr(detail::extract_exception_from_failure<exception_type>(o))
{
this->_state._status.set_have_exception(true);
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_make_error_code_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(const failure_type<T> &o,
explicit_make_error_code_compatible_copy_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_copy_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
: base{in_place_type<typename base::_error_type>, make_error_code(detail::extract_error_from_failure<error_type>(o))}
, _ptr()
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
constexpr basic_outcome(const failure_type<T, U> &o, explicit_compatible_copy_conversion_tag /*unused*/ = explicit_compatible_copy_conversion_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T> &&detail::is_nothrow_constructible<exception_type, U>) // NOLINT
: base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(o)}
, _ptr(detail::extract_exception_from_failure<exception_type>(o))
{
if(!o.has_error())
{
this->_state._status.set_have_error(false);
}
if(o.has_exception())
{
this->_state._status.set_have_exception(true);
}
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(failure_type<T> &&o,
error_failure_tag /*unused*/ = error_failure_tag()) noexcept(detail::is_nothrow_constructible<error_type, T>) // NOLINT
: base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o))}
, _ptr()
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_compatible_conversion<void, void, T, void>))
constexpr basic_outcome(failure_type<T> &&o,
exception_failure_tag /*unused*/ = exception_failure_tag()) noexcept(detail::is_nothrow_constructible<exception_type, T>) // NOLINT
: base()
, _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T> &&>(o)))
{
this->_state._status.set_have_exception(true);
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<T>::value && predicate::template enable_make_error_code_compatible_conversion<void, T, void, void>))
constexpr basic_outcome(failure_type<T> &&o,
explicit_make_error_code_compatible_move_conversion_tag /*unused*/ =
explicit_make_error_code_compatible_move_conversion_tag()) noexcept(noexcept(make_error_code(std::declval<T>()))) // NOLINT
: base{in_place_type<typename base::_error_type>, make_error_code(detail::extract_error_from_failure<error_type>(static_cast<failure_type<T> &&>(o)))}
, _ptr()
{
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_copy_construction(this, o);
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!std::is_void<U>::value && predicate::template enable_compatible_conversion<void, T, U, void>))
constexpr basic_outcome(failure_type<T, U> &&o, explicit_compatible_move_conversion_tag /*unused*/ = explicit_compatible_move_conversion_tag()) noexcept(
detail::is_nothrow_constructible<error_type, T> &&detail::is_nothrow_constructible<exception_type, U>) // NOLINT
: base{in_place_type<typename base::_error_type>, detail::extract_error_from_failure<error_type>(static_cast<failure_type<T, U> &&>(o))}
, _ptr(detail::extract_exception_from_failure<exception_type>(static_cast<failure_type<T, U> &&>(o)))
{
if(!o.has_error())
{
this->_state._status.set_have_error(false);
}
if(o.has_exception())
{
this->_state._status.set_have_exception(true);
}
hooks::set_spare_storage(this, o.spare_storage());
no_value_policy_type::on_outcome_move_construction(this, static_cast<failure_type<T, U> &&>(o));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
using base::operator==;
using base::operator!=;
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, class W)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<detail::devoid<value_type>>() == std::declval<detail::devoid<T>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<error_type>>() == std::declval<detail::devoid<U>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<exception_type>>() == std::declval<detail::devoid<V>>()))
constexpr bool operator==(const basic_outcome<T, U, V, W> &o) const noexcept( //
noexcept(std::declval<detail::devoid<value_type>>() == std::declval<detail::devoid<T>>()) //
&&noexcept(std::declval<detail::devoid<error_type>>() == std::declval<detail::devoid<U>>()) //
&&noexcept(std::declval<detail::devoid<exception_type>>() == std::declval<detail::devoid<V>>()))
{
if(this->_state._status.have_value() && o._state._status.have_value())
{
return this->_state._value == o._state._value; // NOLINT
}
if(this->_state._status.have_error() && o._state._status.have_error() //
&& this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_state._error == o._state._error && this->_ptr == o._ptr;
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error == o._state._error;
}
if(this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_ptr == o._ptr;
}
return false;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<error_type>() == std::declval<T>()), //
OUTCOME_TEXPR(std::declval<exception_type>() == std::declval<U>()))
constexpr bool operator==(const failure_type<T, U> &o) const noexcept( //
noexcept(std::declval<error_type>() == std::declval<T>()) &&noexcept(std::declval<exception_type>() == std::declval<U>()))
{
if(this->_state._status.have_error() && o._state._status.have_error() //
&& this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_state._error == o.error() && this->_ptr == o.exception();
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error == o.error();
}
if(this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_ptr == o.exception();
}
return false;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, class W)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<detail::devoid<value_type>>() != std::declval<detail::devoid<T>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<error_type>>() != std::declval<detail::devoid<U>>()), //
OUTCOME_TEXPR(std::declval<detail::devoid<exception_type>>() != std::declval<detail::devoid<V>>()))
constexpr bool operator!=(const basic_outcome<T, U, V, W> &o) const noexcept( //
noexcept(std::declval<detail::devoid<value_type>>() != std::declval<detail::devoid<T>>()) //
&&noexcept(std::declval<detail::devoid<error_type>>() != std::declval<detail::devoid<U>>()) //
&&noexcept(std::declval<detail::devoid<exception_type>>() != std::declval<detail::devoid<V>>()))
{
if(this->_state._status.have_value() && o._state._status.have_value())
{
return this->_state._value != o._state._value; // NOLINT
}
if(this->_state._status.have_error() && o._state._status.have_error() //
&& this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_state._error != o._state._error || this->_ptr != o._ptr;
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error != o._state._error;
}
if(this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_ptr != o._ptr;
}
return true;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<error_type>() != std::declval<T>()), //
OUTCOME_TEXPR(std::declval<exception_type>() != std::declval<U>()))
constexpr bool operator!=(const failure_type<T, U> &o) const noexcept( //
noexcept(std::declval<error_type>() == std::declval<T>()) &&noexcept(std::declval<exception_type>() == std::declval<U>()))
{
if(this->_state._status.have_error() && o._state._status.have_error() //
&& this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_state._error != o.error() || this->_ptr != o.exception();
}
if(this->_state._status.have_error() && o._state._status.have_error())
{
return this->_state._error != o.error();
}
if(this->_state._status.have_exception() && o._state._status.have_exception())
{
return this->_ptr != o.exception();
}
return true;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
constexpr void swap(basic_outcome &o) noexcept((std::is_void<value_type>::value || detail::is_nothrow_swappable<value_type>::value) //
&& (std::is_void<error_type>::value || detail::is_nothrow_swappable<error_type>::value) //
&& (std::is_void<exception_type>::value || detail::is_nothrow_swappable<exception_type>::value))
{
#ifdef __cpp_exceptions
constexpr bool value_throws = !std::is_void<value_type>::value && !detail::is_nothrow_swappable<value_type>::value;
constexpr bool error_throws = !std::is_void<error_type>::value && !detail::is_nothrow_swappable<error_type>::value;
constexpr bool exception_throws = !std::is_void<exception_type>::value && !detail::is_nothrow_swappable<exception_type>::value;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
if(!exception_throws && !value_throws && !error_throws)
{
// Simples
this->_state.swap(o._state);
using std::swap;
swap(this->_ptr, o._ptr);
return;
}
struct _
{
basic_outcome &a, &b;
bool exceptioned{false};
bool all_good{false};
~_()
{
if(!all_good)
{
// We lost one of the values
a._state._status.set_have_lost_consistency(true);
b._state._status.set_have_lost_consistency(true);
return;
}
if(exceptioned)
{
// The value + error swap threw an exception. Try to swap back _ptr
try
{
strong_swap(all_good, a._ptr, b._ptr);
}
catch(...)
{
// We lost one of the values
a._state._status.set_have_lost_consistency(true);
b._state._status.set_have_lost_consistency(true);
// throw away second exception
}
// Prevent has_value() == has_error() or has_value() == has_exception()
auto check = [](basic_outcome *t) {
if(t->has_value() && (t->has_error() || t->has_exception()))
{
t->_state._status.set_have_error(false).set_have_exception(false);
t->_state._status.set_have_lost_consistency(true);
}
if(!t->has_value() && !(t->has_error() || t->has_exception()))
{
// Choose error, for no particular reason
t->_state._status.set_have_error(true).set_have_lost_consistency(true);
}
};
check(&a);
check(&b);
}
}
} _{*this, o};
strong_swap(_.all_good, this->_ptr, o._ptr);
_.exceptioned = true;
this->_state.swap(o._state);
_.exceptioned = false;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#else
this->_state.swap(o._state);
using std::swap;
swap(this->_ptr, o._ptr);
#endif
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
failure_type<error_type, exception_type> as_failure() const &
{
if(this->has_error() && this->has_exception())
{
return failure_type<error_type, exception_type>(this->assume_error(), this->assume_exception(), hooks::spare_storage(this));
}
if(this->has_exception())
{
return failure_type<error_type, exception_type>(in_place_type<exception_type>, this->assume_exception(), hooks::spare_storage(this));
}
return failure_type<error_type, exception_type>(in_place_type<error_type>, this->assume_error(), hooks::spare_storage(this));
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
failure_type<error_type, exception_type> as_failure() &&
{
this->_state._status.set_have_moved_from(true);
if(this->has_error() && this->has_exception())
{
return failure_type<error_type, exception_type>(static_cast<S &&>(this->assume_error()), static_cast<P &&>(this->assume_exception()),
hooks::spare_storage(this));
}
if(this->has_exception())
{
return failure_type<error_type, exception_type>(in_place_type<exception_type>, static_cast<P &&>(this->assume_exception()), hooks::spare_storage(this));
}
return failure_type<error_type, exception_type>(in_place_type<error_type>, static_cast<S &&>(this->assume_error()), hooks::spare_storage(this));
}
#ifdef __APPLE__
failure_type<error_type, exception_type> _xcode_workaround_as_failure() &&;
#endif
};
// C++ 20 operator== rewriting should take care of this for us, indeed
// if we don't disable it, we cause Concept recursion to infinity!
#if __cplusplus < 202000L && !_HAS_CXX20
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, //
class R, class S, class P, class N)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<basic_outcome<R, S, P, N>>() == std::declval<basic_result<T, U, V>>()))
constexpr inline bool operator==(const basic_result<T, U, V> &a, const basic_outcome<R, S, P, N> &b) noexcept( //
noexcept(std::declval<basic_outcome<R, S, P, N>>() == std::declval<basic_result<T, U, V>>()))
{
return b == a;
}
#endif
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T, class U, class V, //
class R, class S, class P, class N)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<basic_outcome<R, S, P, N>>() != std::declval<basic_result<T, U, V>>()))
constexpr inline bool operator!=(const basic_result<T, U, V> &a, const basic_outcome<R, S, P, N> &b) noexcept( //
noexcept(std::declval<basic_outcome<R, S, P, N>>() != std::declval<basic_result<T, U, V>>()))
{
return b != a;
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P, class N> inline void swap(basic_outcome<R, S, P, N> &a, basic_outcome<R, S, P, N> &b) noexcept(noexcept(a.swap(b)))
{
a.swap(b);
}
namespace hooks
{
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S, class P, class NoValuePolicy, class U>
constexpr inline void override_outcome_exception(basic_outcome<R, S, P, NoValuePolicy> *o, U &&v) noexcept
{
o->_ptr = static_cast<U &&>(v); // NOLINT
o->_state._status.set_have_exception(true);
}
} // namespace hooks
OUTCOME_V2_NAMESPACE_END
#ifdef __clang__
#pragma clang diagnostic pop
#endif
/* Exception observers for outcome type
(C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (6 commits)
File Created: Oct 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_IMPL_HPP
#define OUTCOME_BASIC_OUTCOME_EXCEPTION_OBSERVERS_IMPL_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace policy
{
template <class R, class S, class P, class NoValuePolicy, class Impl> inline constexpr auto &&base::_exception(Impl &&self) noexcept
{
// Impl will be some internal implementation class which has no knowledge of the _ptr stored
// beneath it. So statically cast, preserving rvalue and constness, to the derived class.
using Outcome = OUTCOME_V2_NAMESPACE::detail::rebind_type<basic_outcome<R, S, P, NoValuePolicy>, decltype(self)>;
#if defined(_MSC_VER) && _MSC_VER < 1920
// VS2017 tries a copy construction in the correct implementation despite that Outcome is always a rvalue or lvalue ref! :(
basic_outcome<R, S, P, NoValuePolicy> &_self = (basic_outcome<R, S, P, NoValuePolicy> &) (self); // NOLINT
#else
Outcome _self = static_cast<Outcome>(self); // NOLINT
#endif
return static_cast<Outcome>(_self)._ptr;
}
} // namespace policy
namespace detail
{
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() & noexcept
{
NoValuePolicy::narrow_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() const &noexcept
{
NoValuePolicy::narrow_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() && noexcept
{
NoValuePolicy::narrow_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::assume_exception() const &&noexcept
{
NoValuePolicy::narrow_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() &
{
NoValuePolicy::wide_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() const &
{
NoValuePolicy::wide_exception_check(*this);
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(*this);
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() &&
{
NoValuePolicy::wide_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
template <class Base, class R, class S, class P, class NoValuePolicy> inline constexpr const typename basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception_type &&basic_outcome_exception_observers<Base, R, S, P, NoValuePolicy>::exception() const &&
{
NoValuePolicy::wide_exception_check(std::move(*this));
return NoValuePolicy::template _exception<R, S, P, NoValuePolicy>(std::move(*this));
}
} // namespace detail
OUTCOME_V2_NAMESPACE_END
#endif
#if !defined(NDEBUG)
OUTCOME_V2_NAMESPACE_BEGIN
// Check is trivial in all ways except default constructibility and standard layout
// static_assert(std::is_trivial<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivial!");
// static_assert(std::is_trivially_default_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially default
// constructible!");
static_assert(std::is_trivially_copyable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially copyable!");
static_assert(std::is_trivially_assignable<basic_outcome<int, long, double, policy::all_narrow>, basic_outcome<int, long, double, policy::all_narrow>>::value,
"outcome<int> is not trivially assignable!");
static_assert(std::is_trivially_destructible<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially destructible!");
static_assert(std::is_trivially_copy_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value,
"outcome<int> is not trivially copy constructible!");
static_assert(std::is_trivially_move_constructible<basic_outcome<int, long, double, policy::all_narrow>>::value,
"outcome<int> is not trivially move constructible!");
static_assert(std::is_trivially_copy_assignable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially copy assignable!");
static_assert(std::is_trivially_move_assignable<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not trivially move assignable!");
// Can't be standard layout as non-static member data is defined in more than one inherited class
// static_assert(std::is_standard_layout<basic_outcome<int, long, double, policy::all_narrow>>::value, "outcome<int> is not a standard layout type!");
OUTCOME_V2_NAMESPACE_END
#endif
#endif
/* Traits for Outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (3 commits)
File Created: March 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_TRAIT_STD_EXCEPTION_HPP
#define OUTCOME_TRAIT_STD_EXCEPTION_HPP
#include <exception>
OUTCOME_V2_NAMESPACE_BEGIN
namespace policy
{
namespace detail
{
/* Pass through `make_exception_ptr` function for `std::exception_ptr`.
*/
inline std::exception_ptr make_exception_ptr(std::exception_ptr v) { return v; }
// Try ADL, if not use fall backs above
template <class T> constexpr inline decltype(auto) exception_ptr(T &&v) { return make_exception_ptr(std::forward<T>(v)); }
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class T> constexpr inline decltype(auto) exception_ptr(T &&v) { return detail::exception_ptr(std::forward<T>(v)); }
namespace detail
{
template <bool has_error_payload> struct _rethrow_exception
{
template <class Exception> explicit _rethrow_exception(Exception && /*unused*/) // NOLINT
{
}
};
template <> struct _rethrow_exception<true>
{
template <class Exception> explicit _rethrow_exception(Exception &&excpt) // NOLINT
{
// ADL
rethrow_exception(policy::exception_ptr(std::forward<Exception>(excpt)));
}
};
} // namespace detail
} // namespace policy
namespace trait
{
namespace detail
{
// Shortcut this for lower build impact
template <> struct _is_exception_ptr_available<std::exception_ptr>
{
static constexpr bool value = true;
using type = std::exception_ptr;
};
} // namespace detail
// std::exception_ptr is an error type
template <> struct is_error_type<std::exception_ptr>
{
static constexpr bool value = true;
};
} // namespace trait
OUTCOME_V2_NAMESPACE_END
#endif
/* A very simple result type
(C) 2018-2020 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
File Created: Apr 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_EXPERIMENTAL_STATUS_RESULT_HPP
#define OUTCOME_EXPERIMENTAL_STATUS_RESULT_HPP
/* Policies for result and outcome
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (4 commits)
File Created: Sep 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_POLICY_FAIL_TO_COMPILE_OBSERVERS_HPP
#define OUTCOME_POLICY_FAIL_TO_COMPILE_OBSERVERS_HPP
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
#define OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE "Attempt to wide observe value, error or " "exception for a basic_result/basic_outcome given an EC or EP type which is not void, and for whom " "trait::is_error_code_available<EC>, trait::is_exception_ptr_available<EC>, and trait::is_exception_ptr_available<EP> " "are all false. Please specify a NoValuePolicy to tell basic_result/basic_outcome what to do, or else use " "a more specific convenience type alias such as unchecked<T, E> to indicate you want the wide " "observers to be narrow, or checked<T, E> to indicate you always want an exception throw etc."
namespace policy
{
struct fail_to_compile_observers : base
{
template <class Impl> static constexpr void wide_value_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, "Attempt to wide observe value, error or " "exception for a basic_result/basic_outcome given an EC or EP type which is not void, and for whom " "trait::is_error_code_available<EC>, trait::is_exception_ptr_available<EC>, and trait::is_exception_ptr_available<EP> " "are all false. Please specify a NoValuePolicy to tell basic_result/basic_outcome what to do, or else use " "a more specific convenience type alias such as unchecked<T, E> to indicate you want the wide " "observers to be narrow, or checked<T, E> to indicate you always want an exception throw etc."); }
template <class Impl> static constexpr void wide_error_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, "Attempt to wide observe value, error or " "exception for a basic_result/basic_outcome given an EC or EP type which is not void, and for whom " "trait::is_error_code_available<EC>, trait::is_exception_ptr_available<EC>, and trait::is_exception_ptr_available<EP> " "are all false. Please specify a NoValuePolicy to tell basic_result/basic_outcome what to do, or else use " "a more specific convenience type alias such as unchecked<T, E> to indicate you want the wide " "observers to be narrow, or checked<T, E> to indicate you always want an exception throw etc."); }
template <class Impl> static constexpr void wide_exception_check(Impl && /* unused */) { static_assert(!std::is_same<Impl, Impl>::value, "Attempt to wide observe value, error or " "exception for a basic_result/basic_outcome given an EC or EP type which is not void, and for whom " "trait::is_error_code_available<EC>, trait::is_exception_ptr_available<EC>, and trait::is_exception_ptr_available<EP> " "are all false. Please specify a NoValuePolicy to tell basic_result/basic_outcome what to do, or else use " "a more specific convenience type alias such as unchecked<T, E> to indicate you want the wide " "observers to be narrow, or checked<T, E> to indicate you always want an exception throw etc."); }
};
} // namespace policy
#undef OUTCOME_FAIL_TO_COMPILE_OBSERVERS_MESSAGE
OUTCOME_V2_NAMESPACE_END
#endif
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_HPP
#define SYSTEM_ERROR2_HPP
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_ERROR_HPP
#define SYSTEM_ERROR2_ERROR_HPP
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Jun 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
#define SYSTEM_ERROR2_ERRORED_STATUS_CODE_HPP
/* Proposed SG14 status_code
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: May 2020
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_QUICK_STATUS_CODE_FROM_ENUM_HPP
#define SYSTEM_ERROR2_QUICK_STATUS_CODE_FROM_ENUM_HPP
/* Proposed SG14 status_code
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_GENERIC_CODE_HPP
#define SYSTEM_ERROR2_GENERIC_CODE_HPP
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_STATUS_ERROR_HPP
#define SYSTEM_ERROR2_STATUS_ERROR_HPP
/* Proposed SG14 status_code
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_STATUS_CODE_HPP
#define SYSTEM_ERROR2_STATUS_CODE_HPP
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_STATUS_CODE_DOMAIN_HPP
#define SYSTEM_ERROR2_STATUS_CODE_DOMAIN_HPP
/* Proposed SG14 status_code
(C) 2018 - 2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_CONFIG_HPP
#define SYSTEM_ERROR2_CONFIG_HPP
// < 0.1 each
#include <cassert>
#include <cstddef> // for size_t
#include <cstdlib> // for free
// 0.22
#include <type_traits>
// 0.29
#include <atomic>
// 0.28 (0.15 of which is exception_ptr)
#include <exception> // for std::exception
// <new> includes <exception>, <exception> includes <new>
#include <new>
// 0.01
#include <initializer_list>
#ifndef SYSTEM_ERROR2_CONSTEXPR14
#if 0L || __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
//! Defined to be `constexpr` when on C++ 14 or better compilers. Usually automatic, can be overriden.
#define SYSTEM_ERROR2_CONSTEXPR14 constexpr
#else
#define SYSTEM_ERROR2_CONSTEXPR14
#endif
#endif
#ifndef SYSTEM_ERROR2_NORETURN
#if 0L || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#define SYSTEM_ERROR2_NORETURN [[noreturn]]
#endif
#endif
#if !defined(SYSTEM_ERROR2_NORETURN)
#ifdef __has_cpp_attribute
#if __has_cpp_attribute(noreturn)
#define SYSTEM_ERROR2_NORETURN [[noreturn]]
#endif
#endif
#endif
#if !defined(SYSTEM_ERROR2_NORETURN)
#if defined(_MSC_VER)
#define SYSTEM_ERROR2_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
#define SYSTEM_ERROR2_NORETURN __attribute__((__noreturn__))
#else
#define SYSTEM_ERROR2_NORETURN
#endif
#endif
// GCCs before 7 don't grok [[noreturn]] virtual functions, and warn annoyingly
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 7
#undef SYSTEM_ERROR2_NORETURN
#define SYSTEM_ERROR2_NORETURN
#endif
#ifndef SYSTEM_ERROR2_NODISCARD
#if 0L || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
#define SYSTEM_ERROR2_NODISCARD [[nodiscard]]
#endif
#endif
#ifndef SYSTEM_ERROR2_NODISCARD
#ifdef __has_cpp_attribute
#if __has_cpp_attribute(nodiscard)
#define SYSTEM_ERROR2_NODISCARD [[nodiscard]]
#endif
#elif defined(__clang__)
#define SYSTEM_ERROR2_NODISCARD __attribute__((warn_unused_result))
#elif defined(_MSC_VER)
// _Must_inspect_result_ expands into this
#define SYSTEM_ERROR2_NODISCARD __declspec("SAL_name" "(" "\"_Must_inspect_result_\"" "," "\"\"" "," "\"2\"" ")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
#endif
#endif
#ifndef SYSTEM_ERROR2_NODISCARD
#define SYSTEM_ERROR2_NODISCARD
#endif
#ifndef SYSTEM_ERROR2_TRIVIAL_ABI
#if 0L || (__clang_major__ >= 7 && !defined(__APPLE__))
//! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
#define SYSTEM_ERROR2_TRIVIAL_ABI [[clang::trivial_abi]]
#else
#define SYSTEM_ERROR2_TRIVIAL_ABI
#endif
#endif
#ifndef SYSTEM_ERROR2_NAMESPACE
//! The system_error2 namespace name.
#define SYSTEM_ERROR2_NAMESPACE system_error2
//! Begins the system_error2 namespace.
#define SYSTEM_ERROR2_NAMESPACE_BEGIN namespace system_error2 {
//! Ends the system_error2 namespace.
#define SYSTEM_ERROR2_NAMESPACE_END }
#endif
//! Namespace for the library
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! Namespace for user specialised traits
namespace traits
{
/*! Specialise to true if you guarantee that a type is move bitcopying (i.e.
its move constructor equals copying bits from old to new, old is left in a
default constructed state, and calling the destructor on a default constructed
instance is trivial). All trivially copyable types are move bitcopying by
definition, and that is the unspecialised implementation.
*/
template <class T> struct is_move_bitcopying
{
static constexpr bool value = std::is_trivially_copyable<T>::value;
};
} // namespace traits
namespace detail
{
#if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
inline constexpr size_t cstrlen(const char *str)
{
const char *end = nullptr;
for(end = str; *end != 0; ++end) // NOLINT
;
return end - str;
}
#else
inline constexpr size_t cstrlen_(const char *str, size_t acc)
{
return (str[0] == 0) ? acc : cstrlen_(str + 1, acc + 1);
}
inline constexpr size_t cstrlen(const char *str)
{
return cstrlen_(str, 0);
}
#endif
/* A partially compliant implementation of C++20's std::bit_cast function contributed
by Jesse Towner. TODO FIXME Replace with C++ 20 bit_cast when available.
Our bit_cast is only guaranteed to be constexpr when both the input and output
arguments are either integrals or enums. However, this covers most use cases
since the vast majority of status_codes have an underlying type that is either
an integral or enum. We still attempt a constexpr union-based type pun for non-array
input types, which some compilers accept. For array inputs, we fall back to
non-constexpr memmove.
*/
template <class T> using is_integral_or_enum = std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value>;
template <class To, class From> using is_static_castable = std::integral_constant<bool, is_integral_or_enum<To>::value && is_integral_or_enum<From>::value>;
template <class To, class From> using is_union_castable = std::integral_constant<bool, !is_static_castable<To, From>::value && !std::is_array<To>::value && !std::is_array<From>::value>;
template <class To, class From> using is_bit_castable = std::integral_constant<bool, sizeof(To) == sizeof(From) && traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
template <class To, class From> union bit_cast_union {
From source;
To target;
};
template <class To, class From,
typename std::enable_if< //
is_bit_castable<To, From>::value //
&& is_static_castable<To, From>::value //
&& !is_union_castable<To, From>::value, //
bool>::type = true> //
constexpr To bit_cast(const From &from) noexcept
{
return static_cast<To>(from);
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
template <class To, class From,
typename std::enable_if< //
is_bit_castable<To, From>::value //
&& !is_static_castable<To, From>::value //
&& is_union_castable<To, From>::value, //
bool>::type = true> //
constexpr To bit_cast(const From &from) noexcept
{
return bit_cast_union<To, From>{from}.target;
}
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
template <class To, class From,
typename std::enable_if< //
is_bit_castable<To, From>::value //
&& !is_static_castable<To, From>::value //
&& !is_union_castable<To, From>::value, //
bool>::type = true> //
To bit_cast(const From &from) noexcept
{
bit_cast_union<To, From> ret;
memmove(&ret.source, &from, sizeof(ret.source));
return ret.target;
}
/* erasure_cast performs a bit_cast with additional rules to handle types
of differing sizes. For integral & enum types, it may perform a narrowing
or widing conversion with static_cast if necessary, before doing the final
conversion with bit_cast. When casting to or from non-integral, non-enum
types it may insert the value into another object with extra padding bytes
to satisfy bit_cast's preconditions that both types have the same size. */
template <class To, class From> using is_erasure_castable = std::integral_constant<bool, traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
template <class T, bool = std::is_enum<T>::value> struct identity_or_underlying_type
{
using type = T;
};
template <class T> struct identity_or_underlying_type<T, true>
{
using type = typename std::underlying_type<T>::type;
};
template <class OfSize, class OfSign>
using erasure_integer_type = typename std::conditional<std::is_signed<typename identity_or_underlying_type<OfSign>::type>::value, typename std::make_signed<typename identity_or_underlying_type<OfSize>::type>::type, typename std::make_unsigned<typename identity_or_underlying_type<OfSize>::type>::type>::type;
template <class ErasedType, std::size_t N> struct padded_erasure_object
{
static_assert(traits::is_move_bitcopying<ErasedType>::value, "ErasedType must be TriviallyCopyable or MoveBitcopying");
static_assert(alignof(ErasedType) <= sizeof(ErasedType), "ErasedType must not be over-aligned");
ErasedType value;
char padding[N];
constexpr explicit padded_erasure_object(const ErasedType &v) noexcept
: value(v)
, padding{}
{
}
};
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && (sizeof(To) == sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(from); }
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && is_static_castable<To, From>::value && (sizeof(To) < sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return static_cast<To>(bit_cast<erasure_integer_type<From, To>>(from)); }
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && is_static_castable<To, From>::value && (sizeof(To) > sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(static_cast<erasure_integer_type<To, From>>(from)); }
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) < sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept
{
return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value;
}
template <class To, class From, typename std::enable_if<is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) > sizeof(From)), bool>::type = true> constexpr To erasure_cast(const From &from) noexcept
{
return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from});
}
} // namespace detail
SYSTEM_ERROR2_NAMESPACE_END
#ifndef SYSTEM_ERROR2_FATAL
#ifdef SYSTEM_ERROR2_NOT_POSIX
#error If SYSTEM_ERROR2_NOT_POSIX is defined, you must define your own SYSTEM_ERROR2_FATAL implementation!
#endif
#include <cstdlib> // for abort
#ifdef __APPLE__
#include <unistd.h> // for write
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
namespace detail
{
namespace avoid_stdio_include
{
#if !defined(__APPLE__) && !defined(_MSC_VER)
extern "C" ptrdiff_t write(int, const void *, size_t);
#elif defined(_MSC_VER)
extern ptrdiff_t write(int, const void *, size_t);
#if (defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64)) || (defined(__arm__) || defined(_M_ARM))
#pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YA_JHPEBX_K@Z=write")
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
#pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YAHHPBXI@Z=_write")
#else
#error Unknown architecture
#endif
#endif
} // namespace avoid_stdio_include
inline void do_fatal_exit(const char *msg)
{
using namespace avoid_stdio_include;
write(2 /*stderr*/, msg, cstrlen(msg));
write(2 /*stderr*/, "\n", 1);
abort();
}
} // namespace detail
SYSTEM_ERROR2_NAMESPACE_END
//! Prints msg to stderr, and calls `std::terminate()`. Can be overriden via predefinition.
#define SYSTEM_ERROR2_FATAL(msg) ::SYSTEM_ERROR2_NAMESPACE::detail::do_fatal_exit(msg)
#endif
#endif
#include <cstring> // for strchr
SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! The main workhorse of the system_error2 library, can be typed (`status_code<DomainType>`), erased-immutable (`status_code<void>`) or erased-mutable (`status_code<erased<T>>`).
Be careful of placing these into containers! Equality and inequality operators are
*semantic* not exact. Therefore two distinct items will test true! To help prevent
surprise on this, `operator<` and `std::hash<>` are NOT implemented in order to
trap potential incorrectness. Define your own custom comparison functions for your
container which perform exact comparisons.
*/
template <class DomainType> class status_code;
class _generic_code_domain;
//! The generic code is a status code with the generic code domain, which is that of `errc` (POSIX).
using generic_code = status_code<_generic_code_domain>;
namespace detail
{
template <class StatusCode> class indirecting_domain;
template <class T> struct status_code_sizer
{
void *a;
T b;
};
template <class To, class From> struct type_erasure_is_safe
{
static constexpr bool value = traits::is_move_bitcopying<From>::value //
&& (sizeof(status_code_sizer<From>) <= sizeof(status_code_sizer<To>));
};
/* We are severely limited by needing to retain C++ 11 compatibility when doing
constexpr string parsing. MSVC lets you throw exceptions within a constexpr
evaluation context when exceptions are globally disabled, but won't let you
divide by zero, even if never evaluated, ever in constexpr. GCC and clang won't
let you throw exceptions, ever, if exceptions are globally disabled. So let's
use the trick of divide by zero in constexpr on GCC and clang if and only if
exceptions are globally disabled.
*/
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdiv-by-zero"
#endif
#if defined(__cpp_exceptions) || (defined(_MSC_VER) && !defined(__clang__))
#define SYSTEM_ERROR2_FAIL_CONSTEXPR(msg) throw msg
#else
#define SYSTEM_ERROR2_FAIL_CONSTEXPR(msg) ((void) msg, 1 / 0)
#endif
constexpr inline unsigned long long parse_hex_byte(char c) { return ('0' <= c && c <= '9') ? (c - '0') : ('a' <= c && c <= 'f') ? (10 + c - 'a') : ('A' <= c && c <= 'F') ? (10 + c - 'A') : SYSTEM_ERROR2_FAIL_CONSTEXPR("Invalid character in UUID"); }
constexpr inline unsigned long long parse_uuid2(const char *s)
{
return ((parse_hex_byte(s[0]) << 0) | (parse_hex_byte(s[1]) << 4) | (parse_hex_byte(s[2]) << 8) | (parse_hex_byte(s[3]) << 12) | (parse_hex_byte(s[4]) << 16) | (parse_hex_byte(s[5]) << 20) | (parse_hex_byte(s[6]) << 24) | (parse_hex_byte(s[7]) << 28) | (parse_hex_byte(s[9]) << 32) | (parse_hex_byte(s[10]) << 36) |
(parse_hex_byte(s[11]) << 40) | (parse_hex_byte(s[12]) << 44) | (parse_hex_byte(s[14]) << 48) | (parse_hex_byte(s[15]) << 52) | (parse_hex_byte(s[16]) << 56) | (parse_hex_byte(s[17]) << 60)) //
^ //
((parse_hex_byte(s[19]) << 0) | (parse_hex_byte(s[20]) << 4) | (parse_hex_byte(s[21]) << 8) | (parse_hex_byte(s[22]) << 12) | (parse_hex_byte(s[24]) << 16) | (parse_hex_byte(s[25]) << 20) | (parse_hex_byte(s[26]) << 24) | (parse_hex_byte(s[27]) << 28) | (parse_hex_byte(s[28]) << 32) |
(parse_hex_byte(s[29]) << 36) | (parse_hex_byte(s[30]) << 40) | (parse_hex_byte(s[31]) << 44) | (parse_hex_byte(s[32]) << 48) | (parse_hex_byte(s[33]) << 52) | (parse_hex_byte(s[34]) << 56) | (parse_hex_byte(s[35]) << 60));
}
template <size_t N> constexpr inline unsigned long long parse_uuid_from_array(const char (&uuid)[N]) { return (N == 37) ? parse_uuid2(uuid) : ((N == 39) ? parse_uuid2(uuid + 1) : SYSTEM_ERROR2_FAIL_CONSTEXPR("UUID does not have correct length")); }
template <size_t N> constexpr inline unsigned long long parse_uuid_from_pointer(const char *uuid) { return (N == 36) ? parse_uuid2(uuid) : ((N == 38) ? parse_uuid2(uuid + 1) : SYSTEM_ERROR2_FAIL_CONSTEXPR("UUID does not have correct length")); }
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
static constexpr unsigned long long test_uuid_parse = parse_uuid_from_array("430f1201-94fc-06c7-430f-120194fc06c7");
//static constexpr unsigned long long test_uuid_parse2 = parse_uuid_from_array("x30f1201-94fc-06c7-430f-120194fc06c7");
} // namespace detail
/*! Abstract base class for a coding domain of a status code.
*/
class status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class indirecting_domain;
public:
//! Type of the unique id for this domain.
using unique_id_type = unsigned long long;
/*! (Potentially thread safe) Reference to a message string.
Be aware that you cannot add payload to implementations of this class.
You get exactly the `void *[3]` array to keep state, this is usually
sufficient for a `std::shared_ptr<>` or a `std::string`.
You can install a handler to be called when this object is copied,
moved and destructed. This takes the form of a C function pointer.
*/
class string_ref
{
public:
//! The value type
using value_type = const char;
//! The size type
using size_type = size_t;
//! The pointer type
using pointer = const char *;
//! The const pointer type
using const_pointer = const char *;
//! The iterator type
using iterator = const char *;
//! The const iterator type
using const_iterator = const char *;
protected:
//! The operation occurring
enum class _thunk_op
{
copy,
move,
destruct
};
//! The prototype of the handler function. Copies can throw, moves and destructs cannot.
using _thunk_spec = void (*)(string_ref *dest, const string_ref *src, _thunk_op op);
#ifndef NDEBUG
private:
static void _checking_string_thunk(string_ref *dest, const string_ref *src, _thunk_op /*unused*/) noexcept
{
(void) dest;
(void) src;
assert(dest->_thunk == _checking_string_thunk); // NOLINT
assert(src == nullptr || src->_thunk == _checking_string_thunk); // NOLINT
// do nothing
}
protected:
#endif
//! Pointers to beginning and end of character range
pointer _begin{}, _end{};
//! Three `void*` of state
void *_state[3]{}; // at least the size of a shared_ptr
//! Handler for when operations occur
const _thunk_spec _thunk{nullptr};
constexpr explicit string_ref(_thunk_spec thunk) noexcept
: _thunk(thunk)
{
}
public:
//! Construct from a C string literal
SYSTEM_ERROR2_CONSTEXPR14 explicit string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state0 = nullptr, void *state1 = nullptr, void *state2 = nullptr,
#ifndef NDEBUG
_thunk_spec thunk = _checking_string_thunk
#else
_thunk_spec thunk = nullptr
#endif
) noexcept
: _begin(str)
, _end((len == static_cast<size_type>(-1)) ? (str + detail::cstrlen(str)) : (str + len))
, // NOLINT
_state{state0, state1, state2}
, _thunk(thunk)
{
}
//! Copy construct the derived implementation.
string_ref(const string_ref &o)
: _begin(o._begin)
, _end(o._end)
, _state{o._state[0], o._state[1], o._state[2]}
, _thunk(o._thunk)
{
if(_thunk != nullptr)
{
_thunk(this, &o, _thunk_op::copy);
}
}
//! Move construct the derived implementation.
string_ref(string_ref &&o) noexcept
: _begin(o._begin)
, _end(o._end)
, _state{o._state[0], o._state[1], o._state[2]}
, _thunk(o._thunk)
{
if(_thunk != nullptr)
{
_thunk(this, &o, _thunk_op::move);
}
}
//! Copy assignment
string_ref &operator=(const string_ref &o)
{
if(this != &o)
{
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
string_ref temp(static_cast<string_ref &&>(*this));
this->~string_ref();
try
{
new(this) string_ref(o); // may throw
}
catch(...)
{
new(this) string_ref(static_cast<string_ref &&>(temp));
throw;
}
#else
this->~string_ref();
new(this) string_ref(o);
#endif
}
return *this;
}
//! Move assignment
string_ref &operator=(string_ref &&o) noexcept
{
if(this != &o)
{
this->~string_ref();
new(this) string_ref(static_cast<string_ref &&>(o));
}
return *this;
}
//! Destruction
~string_ref()
{
if(_thunk != nullptr)
{
_thunk(this, nullptr, _thunk_op::destruct);
}
_begin = _end = nullptr;
}
//! Returns whether the reference is empty or not
SYSTEM_ERROR2_NODISCARD bool empty() const noexcept { return _begin == _end; }
//! Returns the size of the string
size_type size() const noexcept { return _end - _begin; }
//! Returns a null terminated C string
const_pointer c_str() const noexcept { return _begin; }
//! Returns a null terminated C string
const_pointer data() const noexcept { return _begin; }
//! Returns the beginning of the string
iterator begin() noexcept { return _begin; }
//! Returns the beginning of the string
const_iterator begin() const noexcept { return _begin; }
//! Returns the beginning of the string
const_iterator cbegin() const noexcept { return _begin; }
//! Returns the end of the string
iterator end() noexcept { return _end; }
//! Returns the end of the string
const_iterator end() const noexcept { return _end; }
//! Returns the end of the string
const_iterator cend() const noexcept { return _end; }
};
/*! A reference counted, threadsafe reference to a message string.
*/
class atomic_refcounted_string_ref : public string_ref
{
struct _allocated_msg
{
mutable std::atomic<unsigned> count{1};
};
_allocated_msg *&_msg() noexcept { return reinterpret_cast<_allocated_msg *&>(this->_state[0]); } // NOLINT
const _allocated_msg *_msg() const noexcept { return reinterpret_cast<const _allocated_msg *>(this->_state[0]); } // NOLINT
static void _refcounted_string_thunk(string_ref *_dest, const string_ref *_src, _thunk_op op) noexcept
{
auto dest = static_cast<atomic_refcounted_string_ref *>(_dest); // NOLINT
auto src = static_cast<const atomic_refcounted_string_ref *>(_src); // NOLINT
(void) src;
assert(dest->_thunk == _refcounted_string_thunk); // NOLINT
assert(src == nullptr || src->_thunk == _refcounted_string_thunk); // NOLINT
switch(op)
{
case _thunk_op::copy:
{
if(dest->_msg() != nullptr)
{
auto count = dest->_msg()->count.fetch_add(1, std::memory_order_relaxed);
(void) count;
assert(count != 0); // NOLINT
}
return;
}
case _thunk_op::move:
{
assert(src); // NOLINT
auto msrc = const_cast<atomic_refcounted_string_ref *>(src); // NOLINT
msrc->_begin = msrc->_end = nullptr;
msrc->_state[0] = msrc->_state[1] = msrc->_state[2] = nullptr;
return;
}
case _thunk_op::destruct:
{
if(dest->_msg() != nullptr)
{
auto count = dest->_msg()->count.fetch_sub(1, std::memory_order_release);
if(count == 1)
{
std::atomic_thread_fence(std::memory_order_acquire);
free((void *) dest->_begin); // NOLINT
delete dest->_msg(); // NOLINT
}
}
}
}
}
public:
//! Construct from a C string literal allocated using `malloc()`.
explicit atomic_refcounted_string_ref(const char *str, size_type len = static_cast<size_type>(-1), void *state1 = nullptr, void *state2 = nullptr) noexcept
: string_ref(str, len, new(std::nothrow) _allocated_msg, state1, state2, _refcounted_string_thunk)
{
if(_msg() == nullptr)
{
free((void *) this->_begin); // NOLINT
_msg() = nullptr; // disabled
this->_begin = "failed to get message from system";
this->_end = strchr(this->_begin, 0);
return;
}
}
};
private:
unique_id_type _id;
protected:
/*! Use [https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h](https://www.random.org/cgi-bin/randbyte?nbytes=8&format=h) to get a random 64 bit id.
Do NOT make up your own value. Do NOT use zero.
*/
constexpr explicit status_code_domain(unique_id_type id) noexcept
: _id(id)
{
}
/*! UUID constructor, where input is constexpr parsed into a `unique_id_type`.
*/
template <size_t N>
constexpr explicit status_code_domain(const char (&uuid)[N]) noexcept
: _id(detail::parse_uuid_from_array<N>(uuid))
{
}
template <size_t N> struct _uuid_size
{
};
//! Alternative UUID constructor
template <size_t N>
constexpr explicit status_code_domain(const char *uuid, _uuid_size<N> /*unused*/) noexcept
: _id(detail::parse_uuid_from_pointer<N>(uuid))
{
}
//! No public copying at type erased level
status_code_domain(const status_code_domain &) = default;
//! No public moving at type erased level
status_code_domain(status_code_domain &&) = default;
//! No public assignment at type erased level
status_code_domain &operator=(const status_code_domain &) = default;
//! No public assignment at type erased level
status_code_domain &operator=(status_code_domain &&) = default;
//! No public destruction at type erased level
~status_code_domain() = default;
public:
//! True if the unique ids match.
constexpr bool operator==(const status_code_domain &o) const noexcept { return _id == o._id; }
//! True if the unique ids do not match.
constexpr bool operator!=(const status_code_domain &o) const noexcept { return _id != o._id; }
//! True if this unique is lower than the other's unique id.
constexpr bool operator<(const status_code_domain &o) const noexcept { return _id < o._id; }
//! Returns the unique id used to identify identical category instances.
constexpr unique_id_type id() const noexcept { return _id; }
//! Name of this category.
virtual string_ref name() const noexcept = 0;
protected:
//! True if code means failure.
virtual bool _do_failure(const status_code<void> &code) const noexcept = 0;
//! True if code is (potentially non-transitively) equivalent to another code in another domain.
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept = 0;
//! Returns the generic code closest to this code, if any.
virtual generic_code _generic_code(const status_code<void> &code) const noexcept = 0;
//! Return a reference to a string textually representing a code.
virtual string_ref _do_message(const status_code<void> &code) const noexcept = 0;
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
//! Throw a code as a C++ exception.
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const = 0;
#else
// Keep a vtable slot for binary compatibility
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> & /*code*/) const { abort(); }
#endif
// For a `status_code<erased<T>>` only, copy from `src` to `dst`. Default implementation uses `memcpy()`.
virtual void _do_erased_copy(status_code<void> &dst, const status_code<void> &src, size_t bytes) const { memcpy(&dst, &src, bytes); } // NOLINT
// For a `status_code<erased<T>>` only, destroy the erased value type. Default implementation does nothing.
virtual void _do_erased_destroy(status_code<void> &code, size_t bytes) const noexcept // NOLINT
{
(void) code;
(void) bytes;
}
};
SYSTEM_ERROR2_NAMESPACE_END
#endif
#if (__cplusplus >= 201700 || _HAS_CXX17) && !defined(SYSTEM_ERROR2_DISABLE_STD_IN_PLACE)
// 0.26
#include <utility> // for in_place
SYSTEM_ERROR2_NAMESPACE_BEGIN
using in_place_t = std::in_place_t;
using std::in_place;
SYSTEM_ERROR2_NAMESPACE_END
#else
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! Aliases `std::in_place_t` if on C++ 17 or later, else defined locally.
struct in_place_t
{
explicit in_place_t() = default;
};
//! Aliases `std::in_place` if on C++ 17 or later, else defined locally.
constexpr in_place_t in_place{};
SYSTEM_ERROR2_NAMESPACE_END
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! Namespace for user injected mixins
namespace mixins
{
template <class Base, class T> struct mixin : public Base
{
using Base::Base;
};
} // namespace mixins
/*! A tag for an erased value type for `status_code<D>`.
Available only if `ErasedType` satisfies `traits::is_move_bitcopying<ErasedType>::value`.
*/
template <class ErasedType, //
typename std::enable_if<traits::is_move_bitcopying<ErasedType>::value, bool>::type = true>
struct erased
{
using value_type = ErasedType;
};
/*! Specialise this template to quickly wrap a third party enumeration into a
custom status code domain.
Use like this:
```c++
SYSTEM_ERROR2_NAMESPACE_BEGIN
template <> struct quick_status_code_from_enum<AnotherCode> : quick_status_code_from_enum_defaults<AnotherCode>
{
// Text name of the enum
static constexpr const auto domain_name = "Another Code";
// Unique UUID for the enum. PLEASE use https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
static constexpr const auto domain_uuid = "{be201f65-3962-dd0e-1266-a72e63776a42}";
// Map of each enum value to its text string, and list of semantically equivalent errc's
static const std::initializer_list<mapping> &value_mappings()
{
static const std::initializer_list<mapping<AnotherCode>> v = {
// Format is: { enum value, "string representation", { list of errc mappings ... } }
{AnotherCode::success1, "Success 1", {errc::success}}, //
{AnotherCode::goaway, "Go away", {errc::permission_denied}}, //
{AnotherCode::success2, "Success 2", {errc::success}}, //
{AnotherCode::error2, "Error 2", {}}, //
};
return v;
}
// Completely optional definition of mixin for the status code synthesised from `Enum`. It can be omitted.
template <class Base> struct mixin : Base
{
using Base::Base;
constexpr int custom_method() const { return 42; }
};
};
SYSTEM_ERROR2_NAMESPACE_END
```
Note that if the `errc` mapping contains `errc::success`, then
the enumeration value is considered to be a successful value.
Otherwise it is considered to be a failure value.
The first value in the `errc` mapping is the one chosen as the
`generic_code` conversion. Other values are used during equivalence
comparisons.
*/
template <class Enum> struct quick_status_code_from_enum;
namespace detail
{
template <class T> struct is_status_code
{
static constexpr bool value = false;
};
template <class T> struct is_status_code<status_code<T>>
{
static constexpr bool value = true;
};
template <class T> struct is_erased_status_code
{
static constexpr bool value = false;
};
template <class T> struct is_erased_status_code<status_code<erased<T>>>
{
static constexpr bool value = true;
};
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ >= 8
// From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4436.pdf
namespace impl
{
template <typename... Ts> struct make_void
{
using type = void;
};
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
template <class...> struct types
{
using type = types;
};
template <template <class...> class T, class types, class = void> struct test_apply
{
using type = void;
};
template <template <class...> class T, class... Ts> struct test_apply<T, types<Ts...>, void_t<T<Ts...>>>
{
using type = T<Ts...>;
};
} // namespace impl
template <template <class...> class T, class... Ts> using test_apply = impl::test_apply<T, impl::types<Ts...>>;
template <class T, class... Args> using get_make_status_code_result = decltype(make_status_code(std::declval<T>(), std::declval<Args>()...));
template <class... Args> using safe_get_make_status_code_result = test_apply<get_make_status_code_result, Args...>;
#else
// ICE avoidance form for GCCs before 8. Note this form doesn't prevent recursive make_status_code ADL instantation,
// so in certain corner cases this will break. On the other hand, more useful than an ICE.
namespace impl
{
template <typename... Ts> struct make_void
{
using type = void;
};
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
template <class...> struct types
{
using type = types;
};
template <typename Types, typename = void> struct make_status_code_rettype
{
using type = void;
};
template <typename... Args> using get_make_status_code_result = decltype(make_status_code(std::declval<Args>()...));
template <typename... Args> struct make_status_code_rettype<types<Args...>, void_t<get_make_status_code_result<Args...>>>
{
using type = get_make_status_code_result<Args...>;
};
} // namespace impl
template <class... Args> struct safe_get_make_status_code_result
{
using type = typename impl::make_status_code_rettype<impl::types<Args...>>::type;
};
#endif
} // namespace detail
//! Trait returning true if the type is a status code.
template <class T> struct is_status_code
{
static constexpr bool value = detail::is_status_code<typename std::decay<T>::type>::value || detail::is_erased_status_code<typename std::decay<T>::type>::value;
};
/*! A type erased lightweight status code reflecting empty, success, or failure.
Differs from `status_code<erased<>>` by being always available irrespective of
the domain's value type, but cannot be copied, moved, nor destructed. Thus one
always passes this around by const lvalue reference.
*/
template <> class SYSTEM_ERROR2_TRIVIAL_ABI status_code<void>
{
template <class T> friend class status_code;
public:
//! The type of the domain.
using domain_type = void;
//! The type of the status code.
using value_type = void;
//! The type of a reference to a message string.
using string_ref = typename status_code_domain::string_ref;
protected:
const status_code_domain *_domain{nullptr};
protected:
//! No default construction at type erased level
status_code() = default;
//! No public copying at type erased level
status_code(const status_code &) = default;
//! No public moving at type erased level
status_code(status_code &&) = default;
//! No public assignment at type erased level
status_code &operator=(const status_code &) = default;
//! No public assignment at type erased level
status_code &operator=(status_code &&) = default;
//! No public destruction at type erased level
~status_code() = default;
//! Used to construct a non-empty type erased status code
constexpr explicit status_code(const status_code_domain *v) noexcept
: _domain(v)
{
}
// Used to work around triggering a ubsan failure. Do NOT remove!
constexpr const status_code_domain *_domain_ptr() const noexcept { return _domain; }
public:
//! Return the status code domain.
constexpr const status_code_domain &domain() const noexcept { return *_domain; }
//! True if the status code is empty.
SYSTEM_ERROR2_NODISCARD constexpr bool empty() const noexcept { return _domain == nullptr; }
//! Return a reference to a string textually representing a code.
string_ref message() const noexcept
{
// Avoid MSVC's buggy ternary operator for expensive to destruct things
if(_domain != nullptr)
{
return _domain->_do_message(*this);
}
return string_ref("(empty)");
}
//! True if code means success.
bool success() const noexcept { return (_domain != nullptr) ? !_domain->_do_failure(*this) : false; }
//! True if code means failure.
bool failure() const noexcept { return (_domain != nullptr) ? _domain->_do_failure(*this) : false; }
/*! True if code is strictly (and potentially non-transitively) semantically equivalent to another code in another domain.
Note that usually non-semantic i.e. pure value comparison is used when the other status code has the same domain.
As `equivalent()` will try mapping to generic code, this usually captures when two codes have the same semantic
meaning in `equivalent()`.
*/
template <class T> bool strictly_equivalent(const status_code<T> &o) const noexcept
{
if(_domain && o._domain)
{
return _domain->_do_equivalent(*this, o);
}
// If we are both empty, we are equivalent
if(!_domain && !o._domain)
{
return true; // NOLINT
}
// Otherwise not equivalent
return false;
}
/*! True if code is equivalent, by any means, to another code in another domain (guaranteed transitive).
Firstly `strictly_equivalent()` is run in both directions. If neither succeeds, each domain is asked
for the equivalent generic code and those are compared.
*/
template <class T> inline bool equivalent(const status_code<T> &o) const noexcept;
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
//! Throw a code as a C++ exception.
SYSTEM_ERROR2_NORETURN void throw_exception() const
{
_domain->_do_throw_exception(*this);
abort(); // suppress buggy GCC warning
}
#endif
};
namespace detail
{
template <class DomainType> struct get_domain_value_type
{
using domain_type = DomainType;
using value_type = typename domain_type::value_type;
};
template <class ErasedType> struct get_domain_value_type<erased<ErasedType>>
{
using domain_type = status_code_domain;
using value_type = ErasedType;
};
template <class DomainType> class SYSTEM_ERROR2_TRIVIAL_ABI status_code_storage : public status_code<void>
{
using _base = status_code<void>;
public:
//! The type of the domain.
using domain_type = typename get_domain_value_type<DomainType>::domain_type;
//! The type of the status code.
using value_type = typename get_domain_value_type<DomainType>::value_type;
//! The type of a reference to a message string.
using string_ref = typename domain_type::string_ref;
#ifndef NDEBUG
static_assert(std::is_move_constructible<value_type>::value || std::is_copy_constructible<value_type>::value, "DomainType::value_type is neither move nor copy constructible!");
static_assert(!std::is_default_constructible<value_type>::value || std::is_nothrow_default_constructible<value_type>::value, "DomainType::value_type is not nothrow default constructible!");
static_assert(!std::is_move_constructible<value_type>::value || std::is_nothrow_move_constructible<value_type>::value, "DomainType::value_type is not nothrow move constructible!");
static_assert(std::is_nothrow_destructible<value_type>::value, "DomainType::value_type is not nothrow destructible!");
#endif
// Replace the type erased implementations with type aware implementations for better codegen
//! Return the status code domain.
constexpr const domain_type &domain() const noexcept { return *static_cast<const domain_type *>(this->_domain); }
//! Reset the code to empty.
SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept
{
this->_value.~value_type();
this->_domain = nullptr;
new(&this->_value) value_type();
}
#if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
//! Return a reference to the `value_type`.
constexpr value_type &value() &noexcept { return this->_value; }
//! Return a reference to the `value_type`.
constexpr value_type &&value() &&noexcept { return static_cast<value_type &&>(this->_value); }
#endif
//! Return a reference to the `value_type`.
constexpr const value_type &value() const &noexcept { return this->_value; }
//! Return a reference to the `value_type`.
constexpr const value_type &&value() const &&noexcept { return static_cast<const value_type &&>(this->_value); }
protected:
status_code_storage() = default;
status_code_storage(const status_code_storage &) = default;
SYSTEM_ERROR2_CONSTEXPR14 status_code_storage(status_code_storage &&o) noexcept
: _base(static_cast<status_code_storage &&>(o))
, _value(static_cast<status_code_storage &&>(o)._value)
{
o._domain = nullptr;
}
status_code_storage &operator=(const status_code_storage &) = default;
SYSTEM_ERROR2_CONSTEXPR14 status_code_storage &operator=(status_code_storage &&o) noexcept
{
this->~status_code_storage();
new(this) status_code_storage(static_cast<status_code_storage &&>(o));
return *this;
}
~status_code_storage() = default;
value_type _value{};
struct _value_type_constructor
{
};
template <class... Args>
constexpr status_code_storage(_value_type_constructor /*unused*/, const status_code_domain *v, Args &&... args)
: _base(v)
, _value(static_cast<Args &&>(args)...)
{
}
};
} // namespace detail
/*! A lightweight, typed, status code reflecting empty, success, or failure.
This is the main workhorse of the system_error2 library. Its characteristics reflect the value type
set by its domain type, so if that value type is move-only or trivial, so is this.
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
If it is found, and it generates a status code compatible with this status code, implicit construction
is made available.
You may mix in custom member functions and member function overrides by injecting a specialisation of
`mixins::mixin<Base, YourDomainType>`. Your mixin must inherit from `Base`.
*/
template <class DomainType> class SYSTEM_ERROR2_TRIVIAL_ABI status_code : public mixins::mixin<detail::status_code_storage<DomainType>, DomainType>
{
template <class T> friend class status_code;
using _base = mixins::mixin<detail::status_code_storage<DomainType>, DomainType>;
public:
//! The type of the domain.
using domain_type = DomainType;
//! The type of the status code.
using value_type = typename domain_type::value_type;
//! The type of a reference to a message string.
using string_ref = typename domain_type::string_ref;
protected:
using _base::_base;
public:
//! Default construction to empty
status_code() = default;
//! Copy constructor
status_code(const status_code &) = default;
//! Move constructor
status_code(status_code &&) = default; // NOLINT
//! Copy assignment
status_code &operator=(const status_code &) = default;
//! Move assignment
status_code &operator=(status_code &&) = default; // NOLINT
~status_code() = default;
//! Return a copy of the code.
SYSTEM_ERROR2_CONSTEXPR14 status_code clone() const { return *this; }
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
template <class T, class... Args, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
&& std::is_constructible<status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
bool>::type = true>
constexpr status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
{
}
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
template <class Enum, //
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type, // Enumeration has been activated
typename std::enable_if<std::is_constructible<status_code, QuickStatusCodeType>::value, // Its status code is compatible
bool>::type = true>
constexpr status_code(Enum &&v) noexcept(std::is_nothrow_constructible<status_code, QuickStatusCodeType>::value) // NOLINT
: status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
{
}
//! Explicit in-place construction. Disables if `domain_type::get()` is not a valid expression.
template <class... Args>
constexpr explicit status_code(in_place_t /*unused */, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<Args &&>(args)...)
{
}
//! Explicit in-place construction from initialiser list. Disables if `domain_type::get()` is not a valid expression.
template <class T, class... Args>
constexpr explicit status_code(in_place_t /*unused */, std::initializer_list<T> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), il, static_cast<Args &&>(args)...)
{
}
//! Explicit copy construction from a `value_type`. Disables if `domain_type::get()` is not a valid expression.
constexpr explicit status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), v)
{
}
//! Explicit move construction from a `value_type`. Disables if `domain_type::get()` is not a valid expression.
constexpr explicit status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
: _base(typename _base::_value_type_constructor{}, &domain_type::get(), static_cast<value_type &&>(v))
{
}
/*! Explicit construction from an erased status code. Available only if
`value_type` is trivially copyable or move bitcopying, and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
Does not check if domains are equal.
*/
template <class ErasedType, //
typename std::enable_if<detail::type_erasure_is_safe<ErasedType, value_type>::value, bool>::type = true>
constexpr explicit status_code(const status_code<erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: status_code(detail::erasure_cast<value_type>(v.value()))
{
#if __cplusplus >= 201400
assert(v.domain() == this->domain());
#endif
}
//! Return a reference to a string textually representing a code.
string_ref message() const noexcept
{
// Avoid MSVC's buggy ternary operator for expensive to destruct things
if(this->_domain != nullptr)
{
return string_ref(this->domain()._do_message(*this));
}
return string_ref("(empty)");
}
};
namespace traits
{
template <class DomainType> struct is_move_bitcopying<status_code<DomainType>>
{
static constexpr bool value = is_move_bitcopying<typename DomainType::value_type>::value;
};
} // namespace traits
/*! Type erased, move-only status_code, unlike `status_code<void>` which cannot be moved nor destroyed. Available
only if `erased<>` is available, which is when the domain's type is trivially
copyable or is move relocatable, and if the size of the domain's typed error code is less than or equal to
this erased error code. Copy construction is disabled, but if you want a copy call `.clone()`.
An ADL discovered helper function `make_status_code(T, Args...)` is looked up by one of the constructors.
If it is found, and it generates a status code compatible with this status code, implicit construction
is made available.
*/
template <class ErasedType> class SYSTEM_ERROR2_TRIVIAL_ABI status_code<erased<ErasedType>> : public mixins::mixin<detail::status_code_storage<erased<ErasedType>>, erased<ErasedType>>
{
template <class T> friend class status_code;
using _base = mixins::mixin<detail::status_code_storage<erased<ErasedType>>, erased<ErasedType>>;
public:
//! The type of the domain (void, as it is erased).
using domain_type = void;
//! The type of the erased status code.
using value_type = ErasedType;
//! The type of a reference to a message string.
using string_ref = typename _base::string_ref;
public:
//! Default construction to empty
status_code() = default;
//! Copy constructor
status_code(const status_code &) = delete;
//! Move constructor
status_code(status_code &&) = default; // NOLINT
//! Copy assignment
status_code &operator=(const status_code &) = delete;
//! Move assignment
status_code &operator=(status_code &&) = default; // NOLINT
~status_code()
{
if(nullptr != this->_domain)
{
this->_domain->_do_erased_destroy(*this, sizeof(*this));
}
}
//! Return a copy of the erased code by asking the domain to perform the erased copy.
status_code clone() const
{
if(nullptr == this->_domain)
{
return {};
}
status_code x;
this->_domain->_do_erased_copy(x, *this, sizeof(*this));
return x;
}
/***** KEEP THESE IN SYNC WITH ERRORED_STATUS_CODE *****/
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage
template <class DomainType, //
typename std::enable_if<std::is_trivially_copyable<typename DomainType::value_type>::value //
&& detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
bool>::type = true>
constexpr status_code(const status_code<DomainType> &v) noexcept // NOLINT
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), detail::erasure_cast<value_type>(v.value()))
{
}
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
template <class DomainType, //
typename std::enable_if<detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value, bool>::type = true>
SYSTEM_ERROR2_CONSTEXPR14 status_code(status_code<DomainType> &&v) noexcept // NOLINT
: _base(typename _base::_value_type_constructor{}, v._domain_ptr(), detail::erasure_cast<value_type>(v.value()))
{
v._domain = nullptr;
}
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
template <class T, class... Args, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<!std::is_same<typename std::decay<T>::type, status_code>::value // not copy/move of self
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
&& std::is_constructible<status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
bool>::type = true>
constexpr status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
: status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
{
}
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
template <class Enum, //
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type, // Enumeration has been activated
typename std::enable_if<std::is_constructible<status_code, QuickStatusCodeType>::value, // Its status code is compatible
bool>::type = true>
constexpr status_code(Enum &&v) noexcept(std::is_nothrow_constructible<status_code, QuickStatusCodeType>::value) // NOLINT
: status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
{
}
/**** By rights ought to be removed in any formal standard ****/
//! Reset the code to empty.
SYSTEM_ERROR2_CONSTEXPR14 void clear() noexcept { *this = status_code(); }
//! Return the erased `value_type` by value.
constexpr value_type value() const noexcept { return this->_value; }
};
namespace traits
{
template <class ErasedType> struct is_move_bitcopying<status_code<erased<ErasedType>>>
{
static constexpr bool value = true;
};
} // namespace traits
SYSTEM_ERROR2_NAMESPACE_END
#endif
#include <exception> // for std::exception
SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! Exception type representing a thrown status_code
*/
template <class DomainType> class status_error;
/*! The erased type edition of status_error.
*/
template <> class status_error<void> : public std::exception
{
protected:
//! Constructs an instance. Not publicly available.
status_error() = default;
//! Copy constructor. Not publicly available
status_error(const status_error &) = default;
//! Move constructor. Not publicly available
status_error(status_error &&) = default;
//! Copy assignment. Not publicly available
status_error &operator=(const status_error &) = default;
//! Move assignment. Not publicly available
status_error &operator=(status_error &&) = default;
//! Destructor. Not publicly available.
~status_error() override = default;
public:
//! The type of the status domain
using domain_type = void;
//! The type of the status code
using status_code_type = status_code<void>;
};
/*! Exception type representing a thrown status_code
*/
template <class DomainType> class status_error : public status_error<void>
{
status_code<DomainType> _code;
typename DomainType::string_ref _msgref;
public:
//! The type of the status domain
using domain_type = DomainType;
//! The type of the status code
using status_code_type = status_code<DomainType>;
//! Constructs an instance
explicit status_error(status_code<DomainType> code)
: _code(static_cast<status_code<DomainType> &&>(code))
, _msgref(_code.message())
{
}
//! Return an explanatory string
virtual const char *what() const noexcept override { return _msgref.c_str(); } // NOLINT
//! Returns a reference to the code
const status_code_type &code() const & { return _code; }
//! Returns a reference to the code
status_code_type &code() & { return _code; }
//! Returns a reference to the code
const status_code_type &&code() const && { return _code; }
//! Returns a reference to the code
status_code_type &&code() && { return _code; }
};
SYSTEM_ERROR2_NAMESPACE_END
#endif
#include <cerrno> // for error constants
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! The generic error coding (POSIX)
enum class errc : int
{
success = 0,
unknown = -1,
address_family_not_supported = EAFNOSUPPORT,
address_in_use = EADDRINUSE,
address_not_available = EADDRNOTAVAIL,
already_connected = EISCONN,
argument_list_too_long = E2BIG,
argument_out_of_domain = EDOM,
bad_address = EFAULT,
bad_file_descriptor = EBADF,
bad_message = EBADMSG,
broken_pipe = EPIPE,
connection_aborted = ECONNABORTED,
connection_already_in_progress = EALREADY,
connection_refused = ECONNREFUSED,
connection_reset = ECONNRESET,
cross_device_link = EXDEV,
destination_address_required = EDESTADDRREQ,
device_or_resource_busy = EBUSY,
directory_not_empty = ENOTEMPTY,
executable_format_error = ENOEXEC,
file_exists = EEXIST,
file_too_large = EFBIG,
filename_too_long = ENAMETOOLONG,
function_not_supported = ENOSYS,
host_unreachable = EHOSTUNREACH,
identifier_removed = EIDRM,
illegal_byte_sequence = EILSEQ,
inappropriate_io_control_operation = ENOTTY,
interrupted = EINTR,
invalid_argument = EINVAL,
invalid_seek = ESPIPE,
io_error = EIO,
is_a_directory = EISDIR,
message_size = EMSGSIZE,
network_down = ENETDOWN,
network_reset = ENETRESET,
network_unreachable = ENETUNREACH,
no_buffer_space = ENOBUFS,
no_child_process = ECHILD,
no_link = ENOLINK,
no_lock_available = ENOLCK,
no_message = ENOMSG,
no_protocol_option = ENOPROTOOPT,
no_space_on_device = ENOSPC,
no_stream_resources = ENOSR,
no_such_device_or_address = ENXIO,
no_such_device = ENODEV,
no_such_file_or_directory = ENOENT,
no_such_process = ESRCH,
not_a_directory = ENOTDIR,
not_a_socket = ENOTSOCK,
not_a_stream = ENOSTR,
not_connected = ENOTCONN,
not_enough_memory = ENOMEM,
not_supported = ENOTSUP,
operation_canceled = ECANCELED,
operation_in_progress = EINPROGRESS,
operation_not_permitted = EPERM,
operation_not_supported = EOPNOTSUPP,
operation_would_block = EWOULDBLOCK,
owner_dead = EOWNERDEAD,
permission_denied = EACCES,
protocol_error = EPROTO,
protocol_not_supported = EPROTONOSUPPORT,
read_only_file_system = EROFS,
resource_deadlock_would_occur = EDEADLK,
resource_unavailable_try_again = EAGAIN,
result_out_of_range = ERANGE,
state_not_recoverable = ENOTRECOVERABLE,
stream_timeout = ETIME,
text_file_busy = ETXTBSY,
timed_out = ETIMEDOUT,
too_many_files_open_in_system = ENFILE,
too_many_files_open = EMFILE,
too_many_links = EMLINK,
too_many_symbolic_link_levels = ELOOP,
value_too_large = EOVERFLOW,
wrong_protocol_type = EPROTOTYPE
};
namespace detail
{
SYSTEM_ERROR2_CONSTEXPR14 inline const char *generic_code_message(errc code) noexcept
{
switch(code)
{
case errc::success:
return "Success";
case errc::address_family_not_supported:
return "Address family not supported by protocol";
case errc::address_in_use:
return "Address already in use";
case errc::address_not_available:
return "Cannot assign requested address";
case errc::already_connected:
return "Transport endpoint is already connected";
case errc::argument_list_too_long:
return "Argument list too long";
case errc::argument_out_of_domain:
return "Numerical argument out of domain";
case errc::bad_address:
return "Bad address";
case errc::bad_file_descriptor:
return "Bad file descriptor";
case errc::bad_message:
return "Bad message";
case errc::broken_pipe:
return "Broken pipe";
case errc::connection_aborted:
return "Software caused connection abort";
case errc::connection_already_in_progress:
return "Operation already in progress";
case errc::connection_refused:
return "Connection refused";
case errc::connection_reset:
return "Connection reset by peer";
case errc::cross_device_link:
return "Invalid cross-device link";
case errc::destination_address_required:
return "Destination address required";
case errc::device_or_resource_busy:
return "Device or resource busy";
case errc::directory_not_empty:
return "Directory not empty";
case errc::executable_format_error:
return "Exec format error";
case errc::file_exists:
return "File exists";
case errc::file_too_large:
return "File too large";
case errc::filename_too_long:
return "File name too long";
case errc::function_not_supported:
return "Function not implemented";
case errc::host_unreachable:
return "No route to host";
case errc::identifier_removed:
return "Identifier removed";
case errc::illegal_byte_sequence:
return "Invalid or incomplete multibyte or wide character";
case errc::inappropriate_io_control_operation:
return "Inappropriate ioctl for device";
case errc::interrupted:
return "Interrupted system call";
case errc::invalid_argument:
return "Invalid argument";
case errc::invalid_seek:
return "Illegal seek";
case errc::io_error:
return "Input/output error";
case errc::is_a_directory:
return "Is a directory";
case errc::message_size:
return "Message too long";
case errc::network_down:
return "Network is down";
case errc::network_reset:
return "Network dropped connection on reset";
case errc::network_unreachable:
return "Network is unreachable";
case errc::no_buffer_space:
return "No buffer space available";
case errc::no_child_process:
return "No child processes";
case errc::no_link:
return "Link has been severed";
case errc::no_lock_available:
return "No locks available";
case errc::no_message:
return "No message of desired type";
case errc::no_protocol_option:
return "Protocol not available";
case errc::no_space_on_device:
return "No space left on device";
case errc::no_stream_resources:
return "Out of streams resources";
case errc::no_such_device_or_address:
return "No such device or address";
case errc::no_such_device:
return "No such device";
case errc::no_such_file_or_directory:
return "No such file or directory";
case errc::no_such_process:
return "No such process";
case errc::not_a_directory:
return "Not a directory";
case errc::not_a_socket:
return "Socket operation on non-socket";
case errc::not_a_stream:
return "Device not a stream";
case errc::not_connected:
return "Transport endpoint is not connected";
case errc::not_enough_memory:
return "Cannot allocate memory";
#if ENOTSUP != EOPNOTSUPP
case errc::not_supported:
return "Operation not supported";
#endif
case errc::operation_canceled:
return "Operation canceled";
case errc::operation_in_progress:
return "Operation now in progress";
case errc::operation_not_permitted:
return "Operation not permitted";
case errc::operation_not_supported:
return "Operation not supported";
#if EAGAIN != EWOULDBLOCK
case errc::operation_would_block:
return "Resource temporarily unavailable";
#endif
case errc::owner_dead:
return "Owner died";
case errc::permission_denied:
return "Permission denied";
case errc::protocol_error:
return "Protocol error";
case errc::protocol_not_supported:
return "Protocol not supported";
case errc::read_only_file_system:
return "Read-only file system";
case errc::resource_deadlock_would_occur:
return "Resource deadlock avoided";
case errc::resource_unavailable_try_again:
return "Resource temporarily unavailable";
case errc::result_out_of_range:
return "Numerical result out of range";
case errc::state_not_recoverable:
return "State not recoverable";
case errc::stream_timeout:
return "Timer expired";
case errc::text_file_busy:
return "Text file busy";
case errc::timed_out:
return "Connection timed out";
case errc::too_many_files_open_in_system:
return "Too many open files in system";
case errc::too_many_files_open:
return "Too many open files";
case errc::too_many_links:
return "Too many links";
case errc::too_many_symbolic_link_levels:
return "Too many levels of symbolic links";
case errc::value_too_large:
return "Value too large for defined data type";
case errc::wrong_protocol_type:
return "Protocol wrong type for socket";
default:
return "unknown";
}
}
} // namespace detail
/*! The implementation of the domain for generic status codes, those mapped by `errc` (POSIX).
*/
class _generic_code_domain : public status_code_domain
{
template <class> friend class status_code;
template <class StatusCode> friend class detail::indirecting_domain;
using _base = status_code_domain;
public:
//! The value type of the generic code, which is an `errc` as per POSIX.
using value_type = errc;
using string_ref = _base::string_ref;
public:
//! Default constructor
constexpr explicit _generic_code_domain(typename _base::unique_id_type id = 0x746d6354f4f733e9) noexcept
: _base(id)
{
}
_generic_code_domain(const _generic_code_domain &) = default;
_generic_code_domain(_generic_code_domain &&) = default;
_generic_code_domain &operator=(const _generic_code_domain &) = default;
_generic_code_domain &operator=(_generic_code_domain &&) = default;
~_generic_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr generic_code_domain variable.
static inline constexpr const _generic_code_domain &get();
virtual _base::string_ref name() const noexcept override { return string_ref("generic domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
return static_cast<const generic_code &>(code).value() != errc::success; // NOLINT
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
{
assert(code1.domain() == *this); // NOLINT
const auto &c1 = static_cast<const generic_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
return static_cast<const generic_code &>(code); // NOLINT
}
virtual _base::string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const generic_code &>(code); // NOLINT
return string_ref(detail::generic_code_message(c.value()));
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const generic_code &>(code); // NOLINT
throw status_error<_generic_code_domain>(c);
}
#endif
};
//! A specialisation of `status_error` for the generic code domain.
using generic_error = status_error<_generic_code_domain>;
//! A constexpr source variable for the generic code domain, which is that of `errc` (POSIX). Returned by `_generic_code_domain::get()`.
constexpr _generic_code_domain generic_code_domain;
inline constexpr const _generic_code_domain &_generic_code_domain::get()
{
return generic_code_domain;
}
// Enable implicit construction of generic_code from errc
SYSTEM_ERROR2_CONSTEXPR14 inline generic_code make_status_code(errc c) noexcept
{
return generic_code(in_place, c);
}
/*************************************************************************************************************/
template <class T> inline bool status_code<void>::equivalent(const status_code<T> &o) const noexcept
{
if(_domain && o._domain)
{
if(_domain->_do_equivalent(*this, o))
{
return true;
}
if(o._domain->_do_equivalent(o, *this))
{
return true;
}
generic_code c1 = o._domain->_generic_code(o);
if(c1.value() != errc::unknown && _domain->_do_equivalent(*this, c1))
{
return true;
}
generic_code c2 = _domain->_generic_code(*this);
if(c2.value() != errc::unknown && o._domain->_do_equivalent(o, c2))
{
return true;
}
}
// If we are both empty, we are equivalent, otherwise not equivalent
return (!_domain && !o._domain);
}
//! True if the status code's are semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
{
return a.equivalent(b);
}
//! True if the status code's are not semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
{
return !a.equivalent(b);
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class DomainType1, class T, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator==(const status_code<DomainType1> &a, const T &b)
{
return a.equivalent(make_status_code(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class T, class DomainType1, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator==(const T &a, const status_code<DomainType1> &b)
{
return b.equivalent(make_status_code(a));
}
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
template <class DomainType1, class T, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator!=(const status_code<DomainType1> &a, const T &b)
{
return !a.equivalent(make_status_code(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class T, class DomainType1, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator!=(const T &a, const status_code<DomainType1> &b)
{
return !b.equivalent(make_status_code(a));
}
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
template <class DomainType1, class T, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator==(const status_code<DomainType1> &a, const T &b)
{
return a.equivalent(QuickStatusCodeType(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
template <class T, class DomainType1, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator==(const T &a, const status_code<DomainType1> &b)
{
return b.equivalent(QuickStatusCodeType(a));
}
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
template <class DomainType1, class T, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator!=(const status_code<DomainType1> &a, const T &b)
{
return !a.equivalent(QuickStatusCodeType(b));
}
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
template <class T, class DomainType1, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator!=(const T &a, const status_code<DomainType1> &b)
{
return !b.equivalent(QuickStatusCodeType(a));
}
SYSTEM_ERROR2_NAMESPACE_END
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
template <class Enum> class _quick_status_code_from_enum_domain;
//! A status code wrapping `Enum` generated from `quick_status_code_from_enum`.
template <class Enum> using quick_status_code_from_enum_code = status_code<_quick_status_code_from_enum_domain<Enum>>;
//! Defaults for an implementation of `quick_status_code_from_enum<Enum>`
template <class Enum> struct quick_status_code_from_enum_defaults
{
//! The type of the resulting code
using code_type = quick_status_code_from_enum_code<Enum>;
//! Used within `quick_status_code_from_enum` to define a mapping of enumeration value with its status code
struct mapping
{
//! The enumeration type
using enumeration_type = Enum;
//! The value being mapped
const Enum value;
//! A string representation for this enumeration value
const char *message;
//! A list of `errc` equivalents for this enumeration value
const std::initializer_list<errc> code_mappings;
};
//! Used within `quick_status_code_from_enum` to define mixins for the status code wrapping `Enum`
template <class Base> struct mixin : Base
{
using Base::Base;
};
};
/*! The implementation of the domain for status codes wrapping `Enum` generated from `quick_status_code_from_enum`.
*/
template <class Enum> class _quick_status_code_from_enum_domain : public status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class detail::indirecting_domain;
using _base = status_code_domain;
using _src = quick_status_code_from_enum<Enum>;
public:
//! The value type of the quick status code from enum
using value_type = Enum;
using _base::string_ref;
constexpr _quick_status_code_from_enum_domain()
: status_code_domain(_src::domain_uuid, _uuid_size<detail::cstrlen(_src::domain_uuid)>())
{
}
_quick_status_code_from_enum_domain(const _quick_status_code_from_enum_domain &) = default;
_quick_status_code_from_enum_domain(_quick_status_code_from_enum_domain &&) = default;
_quick_status_code_from_enum_domain &operator=(const _quick_status_code_from_enum_domain &) = default;
_quick_status_code_from_enum_domain &operator=(_quick_status_code_from_enum_domain &&) = default;
~_quick_status_code_from_enum_domain() = default;
#if __cplusplus < 201402L && !defined(_MSC_VER)
static inline const _quick_status_code_from_enum_domain &get()
{
static _quick_status_code_from_enum_domain v;
return v;
}
#else
static inline constexpr const _quick_status_code_from_enum_domain &get();
#endif
virtual string_ref name() const noexcept override { return string_ref(_src::domain_name); }
protected:
// Not sure if a hash table is worth it here, most enumerations won't be long enough to be worth it
// Also, until C++ 20's consteval, the hash table would get emitted into the binary, bloating it
static SYSTEM_ERROR2_CONSTEXPR14 const typename _src::mapping *_find_mapping(value_type v) noexcept
{
for(const auto &i : _src::value_mappings())
{
if(i.value == v)
{
return &i;
}
}
return nullptr;
}
virtual bool _do_failure(const status_code<void> &code) const noexcept override
{
assert(code.domain() == *this); // NOLINT
// If `errc::success` is in the generic code mapping, it is not a failure
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
assert(mapping != nullptr);
if(mapping != nullptr)
{
for(errc ec : mapping->code_mappings)
{
if(ec == errc::success)
{
return false;
}
}
}
return true;
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override
{
assert(code1.domain() == *this); // NOLINT
const auto &c1 = static_cast<const quick_status_code_from_enum_code<value_type> &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const quick_status_code_from_enum_code<value_type> &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
const auto *mapping = _find_mapping(c1.value());
assert(mapping != nullptr);
if(mapping != nullptr)
{
for(errc ec : mapping->code_mappings)
{
if(ec == c2.value())
{
return true;
}
}
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override
{
assert(code.domain() == *this); // NOLINT
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
assert(mapping != nullptr);
if(mapping != nullptr)
{
if(mapping->code_mappings.size() > 0)
{
return *mapping->code_mappings.begin();
}
}
return errc::unknown;
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override
{
assert(code.domain() == *this); // NOLINT
const auto *mapping = _find_mapping(static_cast<const quick_status_code_from_enum_code<value_type> &>(code).value());
assert(mapping != nullptr);
if(mapping != nullptr)
{
return string_ref(mapping->message);
}
return string_ref("unknown");
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const quick_status_code_from_enum_code<value_type> &>(code); // NOLINT
throw status_error<_quick_status_code_from_enum_domain>(c);
}
#endif
};
#if __cplusplus >= 201402L || defined(_MSC_VER)
template <class Enum> constexpr _quick_status_code_from_enum_domain<Enum> quick_status_code_from_enum_domain = {};
template <class Enum> inline constexpr const _quick_status_code_from_enum_domain<Enum> &_quick_status_code_from_enum_domain<Enum>::get()
{
return quick_status_code_from_enum_domain<Enum>;
}
#endif
namespace mixins
{
template <class Base, class Enum> struct mixin<Base, _quick_status_code_from_enum_domain<Enum>> : public quick_status_code_from_enum<Enum>::template mixin<Base>
{
using quick_status_code_from_enum<Enum>::template mixin<Base>::mixin;
};
} // namespace mixins
SYSTEM_ERROR2_NAMESPACE_END
#endif
/* Pointer to a SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Sep 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_STATUS_CODE_PTR_HPP
#define SYSTEM_ERROR2_STATUS_CODE_PTR_HPP
SYSTEM_ERROR2_NAMESPACE_BEGIN
namespace detail
{
template <class StatusCode> class indirecting_domain : public status_code_domain
{
template <class DomainType> friend class status_code;
using _base = status_code_domain;
public:
using value_type = StatusCode *;
using _base::string_ref;
constexpr indirecting_domain() noexcept
: _base(0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id() /* unique-ish based on domain's unique id */)
{
}
indirecting_domain(const indirecting_domain &) = default;
indirecting_domain(indirecting_domain &&) = default; // NOLINT
indirecting_domain &operator=(const indirecting_domain &) = default;
indirecting_domain &operator=(indirecting_domain &&) = default; // NOLINT
~indirecting_domain() = default;
#if __cplusplus < 201402L && !defined(_MSC_VER)
static inline const indirecting_domain &get()
{
static indirecting_domain v;
return v;
}
#else
static inline constexpr const indirecting_domain &get();
#endif
virtual string_ref name() const noexcept override { return typename StatusCode::domain_type().name(); } // NOLINT
protected:
using _mycode = status_code<indirecting_domain>;
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const _mycode &>(code); // NOLINT
return typename StatusCode::domain_type()._do_failure(*c.value());
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
{
assert(code1.domain() == *this);
const auto &c1 = static_cast<const _mycode &>(code1); // NOLINT
return typename StatusCode::domain_type()._do_equivalent(*c1.value(), code2);
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const _mycode &>(code); // NOLINT
return typename StatusCode::domain_type()._generic_code(*c.value());
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const _mycode &>(code); // NOLINT
return typename StatusCode::domain_type()._do_message(*c.value());
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const _mycode &>(code); // NOLINT
typename StatusCode::domain_type()._do_throw_exception(*c.value());
std::abort();
}
#endif
virtual void _do_erased_copy(status_code<void> &dst, const status_code<void> &src, size_t /*unused*/) const override // NOLINT
{
// Note that dst will not have its domain set
assert(src.domain() == *this);
auto &d = static_cast<_mycode &>(dst); // NOLINT
const auto &_s = static_cast<const _mycode &>(src); // NOLINT
const StatusCode &s = *_s.value();
new(&d) _mycode(in_place, new StatusCode(s));
}
virtual void _do_erased_destroy(status_code<void> &code, size_t /*unused*/) const noexcept override // NOLINT
{
assert(code.domain() == *this);
auto &c = static_cast<_mycode &>(code); // NOLINT
delete c.value(); // NOLINT
}
};
#if __cplusplus >= 201402L || defined(_MSC_VER)
template <class StatusCode> constexpr indirecting_domain<StatusCode> _indirecting_domain{};
template <class StatusCode> inline constexpr const indirecting_domain<StatusCode> &indirecting_domain<StatusCode>::get() { return _indirecting_domain<StatusCode>; }
#endif
} // namespace detail
/*! Make an erased status code which indirects to a dynamically allocated status code.
This is useful for shoehorning a rich status code with large value type into a small
erased status code like `system_code`, with which the status code generated by this
function is compatible. Note that this function can throw due to `bad_alloc`.
*/
template <class T, typename std::enable_if<is_status_code<T>::value, bool>::type = true> //
inline status_code<erased<typename std::add_pointer<typename std::decay<T>::type>::type>> make_status_code_ptr(T &&v)
{
using status_code_type = typename std::decay<T>::type;
return status_code<detail::indirecting_domain<status_code_type>>(in_place, new status_code_type(static_cast<T &&>(v)));
}
/*! If a status code refers to a `status_code_ptr` which indirects to a status
code of type `StatusCode`, return a pointer to that `StatusCode`. Otherwise return null.
*/
template <class StatusCode, class U, typename std::enable_if<is_status_code<StatusCode>::value, bool>::type = true> inline StatusCode *get_if(status_code<erased<U>> *v) noexcept
{
if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
{
return nullptr;
}
union {
U value;
StatusCode *ret;
};
value = v->value();
return ret;
}
//! \overload Const overload
template <class StatusCode, class U, typename std::enable_if<is_status_code<StatusCode>::value, bool>::type = true> inline const StatusCode *get_if(const status_code<erased<U>> *v) noexcept
{
if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
{
return nullptr;
}
union {
U value;
const StatusCode *ret;
};
value = v->value();
return ret;
}
/*! If a status code refers to a `status_code_ptr`, return the id of the erased
status code's domain. Otherwise return a meaningless number.
*/
template <class U> inline typename status_code_domain::unique_id_type get_id(const status_code<erased<U>> &v) noexcept
{
return 0xc44f7bdeb2cc50e9 ^ v.domain().id();
}
SYSTEM_ERROR2_NAMESPACE_END
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! A `status_code` which is always a failure. The closest equivalent to
`std::error_code`, except it cannot be modified, and is templated.
Differences from `status_code`:
- Never successful (this contract is checked on construction, if fails then it
terminates the process).
- Is immutable.
*/
template <class DomainType> class errored_status_code : public status_code<DomainType>
{
using _base = status_code<DomainType>;
using _base::clear;
using _base::success;
void _check()
{
if(_base::success())
{
std::terminate();
}
}
public:
//! The type of the erased error code.
using typename _base::value_type;
//! The type of a reference to a message string.
using typename _base::string_ref;
//! Default constructor.
errored_status_code() = default;
//! Copy constructor.
errored_status_code(const errored_status_code &) = default;
//! Move constructor.
errored_status_code(errored_status_code &&) = default; // NOLINT
//! Copy assignment.
errored_status_code &operator=(const errored_status_code &) = default;
//! Move assignment.
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
~errored_status_code() = default;
//! Explicitly construct from any similarly erased status code
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
: _base(o)
{
_check();
}
//! Explicitly construct from any similarly erased status code
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
: _base(static_cast<_base &&>(o))
{
_check();
}
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
template <class T, class... Args, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
&& !std::is_same<typename std::decay<T>::type, in_place_t>::value // not in_place_t
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
bool>::type = true>
errored_status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
{
_check();
}
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
template <class Enum, //
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type, // Enumeration has been activated
typename std::enable_if<std::is_constructible<errored_status_code, QuickStatusCodeType>::value, // Its status code is compatible
bool>::type = true>
errored_status_code(Enum &&v) noexcept(std::is_nothrow_constructible<errored_status_code, QuickStatusCodeType>::value) // NOLINT
: errored_status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
{
_check();
}
//! Explicit in-place construction.
template <class... Args>
explicit errored_status_code(in_place_t _, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, Args &&...>::value)
: _base(_, static_cast<Args &&>(args)...)
{
_check();
}
//! Explicit in-place construction from initialiser list.
template <class T, class... Args>
explicit errored_status_code(in_place_t _, std::initializer_list<T> il, Args &&... args) noexcept(std::is_nothrow_constructible<value_type, std::initializer_list<T>, Args &&...>::value)
: _base(_, il, static_cast<Args &&>(args)...)
{
_check();
}
//! Explicit copy construction from a `value_type`.
explicit errored_status_code(const value_type &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: _base(v)
{
_check();
}
//! Explicit move construction from a `value_type`.
explicit errored_status_code(value_type &&v) noexcept(std::is_nothrow_move_constructible<value_type>::value)
: _base(static_cast<value_type &&>(v))
{
_check();
}
/*! Explicit construction from an erased status code. Available only if
`value_type` is trivially destructible and `sizeof(status_code) <= sizeof(status_code<erased<>>)`.
Does not check if domains are equal.
*/
template <class ErasedType, //
typename std::enable_if<detail::type_erasure_is_safe<ErasedType, value_type>::value, bool>::type = true>
explicit errored_status_code(const status_code<erased<ErasedType>> &v) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: errored_status_code(detail::erasure_cast<value_type>(v.value())) // NOLINT
{
assert(v.domain() == this->domain()); // NOLINT
_check();
}
//! Always false (including at compile time), as errored status codes are never successful.
constexpr bool success() const noexcept { return false; }
//! Return a const reference to the `value_type`.
constexpr const value_type &value() const &noexcept { return this->_value; }
};
namespace traits
{
template <class DomainType> struct is_move_bitcopying<errored_status_code<DomainType>>
{
static constexpr bool value = is_move_bitcopying<typename DomainType::value_type>::value;
};
} // namespace traits
template <class ErasedType> class errored_status_code<erased<ErasedType>> : public status_code<erased<ErasedType>>
{
using _base = status_code<erased<ErasedType>>;
using _base::success;
void _check()
{
if(_base::success())
{
std::terminate();
}
}
public:
using value_type = typename _base::value_type;
using string_ref = typename _base::string_ref;
//! Default construction to empty
errored_status_code() = default;
//! Copy constructor
errored_status_code(const errored_status_code &) = default;
//! Move constructor
errored_status_code(errored_status_code &&) = default; // NOLINT
//! Copy assignment
errored_status_code &operator=(const errored_status_code &) = default;
//! Move assignment
errored_status_code &operator=(errored_status_code &&) = default; // NOLINT
~errored_status_code() = default;
//! Explicitly construct from any similarly erased status code
explicit errored_status_code(const _base &o) noexcept(std::is_nothrow_copy_constructible<_base>::value)
: _base(o)
{
_check();
}
//! Explicitly construct from any similarly erased status code
explicit errored_status_code(_base &&o) noexcept(std::is_nothrow_move_constructible<_base>::value)
: _base(static_cast<_base &&>(o))
{
_check();
}
/***** KEEP THESE IN SYNC WITH STATUS_CODE *****/
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage
template <class DomainType, //
typename std::enable_if<std::is_trivially_copyable<typename DomainType::value_type>::value //
&& detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
bool>::type = true>
errored_status_code(const status_code<DomainType> &v) noexcept
: _base(v) // NOLINT
{
_check();
}
//! Implicit copy construction from any other status code if its value type is trivially copyable and it would fit into our storage
template <class DomainType, //
typename std::enable_if<std::is_trivially_copyable<typename DomainType::value_type>::value //
&& detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
bool>::type = true>
errored_status_code(const errored_status_code<DomainType> &v) noexcept
: _base(static_cast<const status_code<DomainType> &>(v)) // NOLINT
{
_check();
}
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
template <class DomainType, //
typename std::enable_if<detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
bool>::type = true>
errored_status_code(status_code<DomainType> &&v) noexcept
: _base(static_cast<status_code<DomainType> &&>(v)) // NOLINT
{
_check();
}
//! Implicit move construction from any other status code if its value type is trivially copyable or move bitcopying and it would fit into our storage
template <class DomainType, //
typename std::enable_if<detail::type_erasure_is_safe<value_type, typename DomainType::value_type>::value,
bool>::type = true>
errored_status_code(errored_status_code<DomainType> &&v) noexcept
: _base(static_cast<status_code<DomainType> &&>(v)) // NOLINT
{
_check();
}
//! Implicit construction from any type where an ADL discovered `make_status_code(T, Args ...)` returns a `status_code`.
template <class T, class... Args, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<T, Args...>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<!std::is_same<typename std::decay<T>::type, errored_status_code>::value // not copy/move of self
&& !std::is_same<typename std::decay<T>::type, value_type>::value // not copy/move of value type
&& is_status_code<MakeStatusCodeResult>::value // ADL makes a status code
&& std::is_constructible<errored_status_code, MakeStatusCodeResult>::value, // ADLed status code is compatible
bool>::type = true>
errored_status_code(T &&v, Args &&... args) noexcept(noexcept(make_status_code(std::declval<T>(), std::declval<Args>()...))) // NOLINT
: errored_status_code(make_status_code(static_cast<T &&>(v), static_cast<Args &&>(args)...))
{
_check();
}
//! Implicit construction from any `quick_status_code_from_enum<Enum>` enumerated type.
template <class Enum, //
class QuickStatusCodeType = typename quick_status_code_from_enum<Enum>::code_type, // Enumeration has been activated
typename std::enable_if<std::is_constructible<errored_status_code, QuickStatusCodeType>::value, // Its status code is compatible
bool>::type = true>
errored_status_code(Enum &&v) noexcept(std::is_nothrow_constructible<errored_status_code, QuickStatusCodeType>::value) // NOLINT
: errored_status_code(QuickStatusCodeType(static_cast<Enum &&>(v)))
{
_check();
}
//! Always false (including at compile time), as errored status codes are never successful.
constexpr bool success() const noexcept { return false; }
//! Return the erased `value_type` by value.
constexpr value_type value() const noexcept { return this->_value; }
};
namespace traits
{
template <class ErasedType> struct is_move_bitcopying<errored_status_code<erased<ErasedType>>>
{
static constexpr bool value = true;
};
} // namespace traits
//! True if the status code's are semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator==(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
{
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
}
//! True if the status code's are semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator==(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
{
return a.equivalent(static_cast<const status_code<DomainType2> &>(b));
}
//! True if the status code's are semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator==(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
{
return static_cast<const status_code<DomainType1> &>(a).equivalent(b);
}
//! True if the status code's are not semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator!=(const errored_status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
{
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
}
//! True if the status code's are not semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator!=(const status_code<DomainType1> &a, const errored_status_code<DomainType2> &b) noexcept
{
return !a.equivalent(static_cast<const status_code<DomainType2> &>(b));
}
//! True if the status code's are not semantically equal via `equivalent()`.
template <class DomainType1, class DomainType2> inline bool operator!=(const errored_status_code<DomainType1> &a, const status_code<DomainType2> &b) noexcept
{
return !static_cast<const status_code<DomainType1> &>(a).equivalent(b);
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class DomainType1, class T, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator==(const errored_status_code<DomainType1> &a, const T &b)
{
return a.equivalent(make_status_code(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class T, class DomainType1, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator==(const T &a, const errored_status_code<DomainType1> &b)
{
return b.equivalent(make_status_code(a));
}
//! True if the status code's are not semantically equal via `equivalent()` to `make_status_code(T)`.
template <class DomainType1, class T, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator!=(const errored_status_code<DomainType1> &a, const T &b)
{
return !a.equivalent(make_status_code(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `make_status_code(T)`.
template <class T, class DomainType1, //
class MakeStatusCodeResult = typename detail::safe_get_make_status_code_result<const T &>::type, // Safe ADL lookup of make_status_code(), returns void if not found
typename std::enable_if<is_status_code<MakeStatusCodeResult>::value, bool>::type = true> // ADL makes a status code
inline bool operator!=(const T &a, const errored_status_code<DomainType1> &b)
{
return !b.equivalent(make_status_code(a));
}
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
template <class DomainType1, class T, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator==(const errored_status_code<DomainType1> &a, const T &b)
{
return a.equivalent(QuickStatusCodeType(b));
}
//! True if the status code's are semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
template <class T, class DomainType1, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator==(const T &a, const errored_status_code<DomainType1> &b)
{
return b.equivalent(QuickStatusCodeType(a));
}
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(b)`.
template <class DomainType1, class T, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator!=(const errored_status_code<DomainType1> &a, const T &b)
{
return !a.equivalent(QuickStatusCodeType(b));
}
//! True if the status code's are not semantically equal via `equivalent()` to `quick_status_code_from_enum<T>::code_type(a)`.
template <class T, class DomainType1, //
class QuickStatusCodeType = typename quick_status_code_from_enum<T>::code_type // Enumeration has been activated
>
inline bool operator!=(const T &a, const errored_status_code<DomainType1> &b)
{
return !b.equivalent(QuickStatusCodeType(a));
}
namespace detail
{
template <class T> struct is_errored_status_code
{
static constexpr bool value = false;
};
template <class T> struct is_errored_status_code<errored_status_code<T>>
{
static constexpr bool value = true;
};
template <class T> struct is_erased_errored_status_code
{
static constexpr bool value = false;
};
template <class T> struct is_erased_errored_status_code<errored_status_code<erased<T>>>
{
static constexpr bool value = true;
};
} // namespace detail
//! Trait returning true if the type is an errored status code.
template <class T> struct is_errored_status_code
{
static constexpr bool value = detail::is_errored_status_code<typename std::decay<T>::type>::value || detail::is_erased_errored_status_code<typename std::decay<T>::type>::value;
};
SYSTEM_ERROR2_NAMESPACE_END
#endif
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_SYSTEM_CODE_HPP
#define SYSTEM_ERROR2_SYSTEM_CODE_HPP
#ifndef SYSTEM_ERROR2_NOT_POSIX
/* Proposed SG14 status_code
(C) 2018-2020 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_POSIX_CODE_HPP
#define SYSTEM_ERROR2_POSIX_CODE_HPP
#ifdef SYSTEM_ERROR2_NOT_POSIX
#error <posix_code.hpp> is not includable when SYSTEM_ERROR2_NOT_POSIX is defined!
#endif
#include <cstring> // for strchr and strerror_r
SYSTEM_ERROR2_NAMESPACE_BEGIN
class _posix_code_domain;
//! A POSIX error code, those returned by `errno`.
using posix_code = status_code<_posix_code_domain>;
//! A specialisation of `status_error` for the POSIX error code domain.
using posix_error = status_error<_posix_code_domain>;
namespace mixins
{
template <class Base> struct mixin<Base, _posix_code_domain> : public Base
{
using Base::Base;
//! Returns a `posix_code` for the current value of `errno`.
static posix_code current() noexcept;
};
} // namespace mixins
/*! The implementation of the domain for POSIX error codes, those returned by `errno`.
*/
class _posix_code_domain : public status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class detail::indirecting_domain;
using _base = status_code_domain;
static _base::string_ref _make_string_ref(int c) noexcept
{
char buffer[1024] = "";
#ifdef _WIN32
strerror_s(buffer, sizeof(buffer), c);
#elif defined(__gnu_linux__) && !defined(__ANDROID__) // handle glibc's weird strerror_r()
char *s = strerror_r(c, buffer, sizeof(buffer)); // NOLINT
if(s != nullptr)
{
strncpy(buffer, s, sizeof(buffer)); // NOLINT
buffer[1023] = 0;
}
#else
strerror_r(c, buffer, sizeof(buffer));
#endif
size_t length = strlen(buffer); // NOLINT
auto *p = static_cast<char *>(malloc(length + 1)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
memcpy(p, buffer, length + 1); // NOLINT
return _base::atomic_refcounted_string_ref(p, length);
}
public:
//! The value type of the POSIX code, which is an `int`
using value_type = int;
using _base::string_ref;
//! Default constructor
constexpr explicit _posix_code_domain(typename _base::unique_id_type id = 0xa59a56fe5f310933) noexcept
: _base(id)
{
}
_posix_code_domain(const _posix_code_domain &) = default;
_posix_code_domain(_posix_code_domain &&) = default;
_posix_code_domain &operator=(const _posix_code_domain &) = default;
_posix_code_domain &operator=(_posix_code_domain &&) = default;
~_posix_code_domain() = default;
//! Constexpr singleton getter. Returns constexpr posix_code_domain variable.
static inline constexpr const _posix_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("posix domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
return static_cast<const posix_code &>(code).value() != 0; // NOLINT
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
{
assert(code1.domain() == *this); // NOLINT
const auto &c1 = static_cast<const posix_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const posix_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == c1.value())
{
return true;
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const posix_code &>(code); // NOLINT
return generic_code(static_cast<errc>(c.value()));
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const posix_code &>(code); // NOLINT
return _make_string_ref(c.value());
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
{
assert(code.domain() == *this); // NOLINT
const auto &c = static_cast<const posix_code &>(code); // NOLINT
throw status_error<_posix_code_domain>(c);
}
#endif
};
//! A constexpr source variable for the POSIX code domain, which is that of `errno`. Returned by `_posix_code_domain::get()`.
constexpr _posix_code_domain posix_code_domain;
inline constexpr const _posix_code_domain &_posix_code_domain::get()
{
return posix_code_domain;
}
namespace mixins
{
template <class Base> inline posix_code mixin<Base, _posix_code_domain>::current() noexcept { return posix_code(errno); }
} // namespace mixins
SYSTEM_ERROR2_NAMESPACE_END
#endif
#else
#endif
#if defined(_WIN32) || 0L
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_NT_CODE_HPP
#define SYSTEM_ERROR2_NT_CODE_HPP
#if !defined(_WIN32) && !0L
#error This file should only be included on Windows
#endif
/* Proposed SG14 status_code
(C) 2018 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
File Created: Feb 2018
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef SYSTEM_ERROR2_WIN32_CODE_HPP
#define SYSTEM_ERROR2_WIN32_CODE_HPP
#if !defined(_WIN32) && !0L
#error This file should only be included on Windows
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! \exclude
namespace win32
{
// A Win32 DWORD
using DWORD = unsigned long;
// Used to retrieve the current Win32 error code
extern DWORD __stdcall GetLastError();
// Used to retrieve a locale-specific message string for some error code
extern DWORD __stdcall FormatMessageW(DWORD dwFlags, const void *lpSource, DWORD dwMessageId, DWORD dwLanguageId, wchar_t *lpBuffer, DWORD nSize, void /*va_list*/ *Arguments);
// Converts UTF-16 message string to UTF-8
extern int __stdcall WideCharToMultiByte(unsigned int CodePage, DWORD dwFlags, const wchar_t *lpWideCharStr, int cchWideChar, char *lpMultiByteStr, int cbMultiByte, const char *lpDefaultChar, int *lpUsedDefaultChar);
#pragma comment(lib, "kernel32.lib")
#if (defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64))
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YAKXZ=GetLastError")
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YAKKPEBXKKPEA_WKPEAX@Z=FormatMessageW")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YAHIKPEB_WHPEADHPEBDPEAH@Z=WideCharToMultiByte")
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YGKXZ=__imp__GetLastError@0")
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YGKKPBXKKPA_WKPAX@Z=__imp__FormatMessageW@28")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YGHIKPB_WHPADHPBDPAH@Z=__imp__WideCharToMultiByte@32")
#elif defined(__arm__) || defined(_M_ARM)
#pragma comment(linker, "/alternatename:?GetLastError@win32@system_error2@@YAKXZ=GetLastError")
#pragma comment(linker, "/alternatename:?FormatMessageW@win32@system_error2@@YAKKPBXKKPA_WKPAX@Z=FormatMessageW")
#pragma comment(linker, "/alternatename:?WideCharToMultiByte@win32@system_error2@@YAHIKPB_WHPADHPBDPAH@Z=WideCharToMultiByte")
#else
#error Unknown architecture
#endif
} // namespace win32
class _win32_code_domain;
class _com_code_domain;
//! (Windows only) A Win32 error code, those returned by `GetLastError()`.
using win32_code = status_code<_win32_code_domain>;
//! (Windows only) A specialisation of `status_error` for the Win32 error code domain.
using win32_error = status_error<_win32_code_domain>;
namespace mixins
{
template <class Base> struct mixin<Base, _win32_code_domain> : public Base
{
using Base::Base;
//! Returns a `win32_code` for the current value of `GetLastError()`.
static inline win32_code current() noexcept;
};
} // namespace mixins
/*! (Windows only) The implementation of the domain for Win32 error codes, those returned by `GetLastError()`.
*/
class _win32_code_domain : public status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class detail::indirecting_domain;
friend class _com_code_domain;
using _base = status_code_domain;
static int _win32_code_to_errno(win32::DWORD c)
{
switch(c)
{
case 0:
return 0;
case 0x1: return ENOSYS;
case 0x2: return ENOENT;
case 0x3: return ENOENT;
case 0x4: return EMFILE;
case 0x5: return EACCES;
case 0x6: return EINVAL;
case 0x8: return ENOMEM;
case 0xc: return EACCES;
case 0xe: return ENOMEM;
case 0xf: return ENODEV;
case 0x10: return EACCES;
case 0x11: return EXDEV;
case 0x13: return EACCES;
case 0x14: return ENODEV;
case 0x15: return EAGAIN;
case 0x19: return EIO;
case 0x1d: return EIO;
case 0x1e: return EIO;
case 0x20: return EACCES;
case 0x21: return ENOLCK;
case 0x27: return ENOSPC;
case 0x37: return ENODEV;
case 0x50: return EEXIST;
case 0x52: return EACCES;
case 0x57: return EINVAL;
case 0x6e: return EIO;
case 0x6f: return ENAMETOOLONG;
case 0x70: return ENOSPC;
case 0x7b: return EINVAL;
case 0x83: return EINVAL;
case 0x8e: return EBUSY;
case 0x91: return ENOTEMPTY;
case 0xaa: return EBUSY;
case 0xb7: return EEXIST;
case 0xd4: return ENOLCK;
case 0x10b: return EINVAL;
case 0x3e3: return ECANCELED;
case 0x3e6: return EACCES;
case 0x3f3: return EIO;
case 0x3f4: return EIO;
case 0x3f5: return EIO;
case 0x4d5: return EAGAIN;
case 0x961: return EBUSY;
case 0x964: return EBUSY;
case 0x2714: return EINTR;
case 0x2719: return EBADF;
case 0x271d: return EACCES;
case 0x271e: return EFAULT;
case 0x2726: return EINVAL;
case 0x2728: return EMFILE;
case 0x2733: return EWOULDBLOCK;
case 0x2734: return EINPROGRESS;
case 0x2735: return EALREADY;
case 0x2736: return ENOTSOCK;
case 0x2737: return EDESTADDRREQ;
case 0x2738: return EMSGSIZE;
case 0x2739: return EPROTOTYPE;
case 0x273a: return ENOPROTOOPT;
case 0x273b: return EPROTONOSUPPORT;
case 0x273d: return EOPNOTSUPP;
case 0x273f: return EAFNOSUPPORT;
case 0x2740: return EADDRINUSE;
case 0x2741: return EADDRNOTAVAIL;
case 0x2742: return ENETDOWN;
case 0x2743: return ENETUNREACH;
case 0x2744: return ENETRESET;
case 0x2745: return ECONNABORTED;
case 0x2746: return ECONNRESET;
case 0x2747: return ENOBUFS;
case 0x2748: return EISCONN;
case 0x2749: return ENOTCONN;
case 0x274c: return ETIMEDOUT;
case 0x274d: return ECONNREFUSED;
case 0x274f: return ENAMETOOLONG;
case 0x2751: return EHOSTUNREACH;
}
return -1;
}
//! Construct from a Win32 error code
static _base::string_ref _make_string_ref(win32::DWORD c) noexcept
{
wchar_t buffer[32768];
win32::DWORD wlen = win32::FormatMessageW(0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/, nullptr, c, 0, buffer, 32768, nullptr);
size_t allocation = wlen + (wlen >> 1);
win32::DWORD bytes;
if(wlen == 0)
{
return _base::string_ref("failed to get message from system");
}
for(;;)
{
auto *p = static_cast<char *>(malloc(allocation)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, buffer, (int) (wlen + 1), p, (int) allocation, nullptr, nullptr);
if(bytes != 0)
{
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
}
free(p); // NOLINT
if(win32::GetLastError() == 0x7a /*ERROR_INSUFFICIENT_BUFFER*/)
{
allocation += allocation >> 2;
continue;
}
return _base::string_ref("failed to get message from system");
}
}
public:
//! The value type of the win32 code, which is a `win32::DWORD`
using value_type = win32::DWORD;
using _base::string_ref;
public:
//! Default constructor
constexpr explicit _win32_code_domain(typename _base::unique_id_type id = 0x8cd18ee72d680f1b) noexcept
: _base(id)
{
}
_win32_code_domain(const _win32_code_domain &) = default;
_win32_code_domain(_win32_code_domain &&) = default;
_win32_code_domain &operator=(const _win32_code_domain &) = default;
_win32_code_domain &operator=(_win32_code_domain &&) = default;
~_win32_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr win32_code_domain variable.
static inline constexpr const _win32_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("win32 domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
return static_cast<const win32_code &>(code).value() != 0; // NOLINT
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
{
assert(code1.domain() == *this);
const auto &c1 = static_cast<const win32_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const win32_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _win32_code_to_errno(c1.value()))
{
return true;
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const win32_code &>(code); // NOLINT
return generic_code(static_cast<errc>(_win32_code_to_errno(c.value())));
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const win32_code &>(code); // NOLINT
return _make_string_ref(c.value());
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const win32_code &>(code); // NOLINT
throw status_error<_win32_code_domain>(c);
}
#endif
};
//! (Windows only) A constexpr source variable for the win32 code domain, which is that of `GetLastError()` (Windows). Returned by `_win32_code_domain::get()`.
constexpr _win32_code_domain win32_code_domain;
inline constexpr const _win32_code_domain &_win32_code_domain::get()
{
return win32_code_domain;
}
namespace mixins
{
template <class Base> inline win32_code mixin<Base, _win32_code_domain>::current() noexcept { return win32_code(win32::GetLastError()); }
} // namespace mixins
SYSTEM_ERROR2_NAMESPACE_END
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
//! \exclude
namespace win32
{
// A Win32 NTSTATUS
using NTSTATUS = long;
// A Win32 HMODULE
using HMODULE = void *;
// Used to retrieve where the NTDLL DLL is mapped into memory
extern HMODULE __stdcall GetModuleHandleW(const wchar_t *lpModuleName);
#pragma comment(lib, "kernel32.lib")
#if (defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64))
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YAPEAXPEB_W@Z=GetModuleHandleW")
#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YGPAXPB_W@Z=__imp__GetModuleHandleW@4")
#elif defined(__arm__) || defined(_M_ARM)
#pragma comment(linker, "/alternatename:?GetModuleHandleW@win32@system_error2@@YAPAXPB_W@Z=GetModuleHandleW")
#else
#error Unknown architecture
#endif
} // namespace win32
class _nt_code_domain;
//! (Windows only) A NT error code, those returned by NT kernel functions.
using nt_code = status_code<_nt_code_domain>;
//! (Windows only) A specialisation of `status_error` for the NT error code domain.
using nt_error = status_error<_nt_code_domain>;
/*! (Windows only) The implementation of the domain for NT error codes, those returned by NT kernel functions.
*/
class _nt_code_domain : public status_code_domain
{
template <class DomainType> friend class status_code;
template <class StatusCode> friend class detail::indirecting_domain;
friend class _com_code_domain;
using _base = status_code_domain;
static int _nt_code_to_errno(win32::NTSTATUS c)
{
if(c >= 0)
{
return 0; // success
}
switch(static_cast<unsigned>(c))
{
case 0x80000002: return EACCES;
case 0x8000000f: return EAGAIN;
case 0x80000010: return EAGAIN;
case 0x80000011: return EBUSY;
case 0xc0000002: return ENOSYS;
case 0xc0000005: return EACCES;
case 0xc0000008: return EINVAL;
case 0xc000000e: return ENOENT;
case 0xc000000f: return ENOENT;
case 0xc0000010: return ENOSYS;
case 0xc0000013: return EAGAIN;
case 0xc0000017: return ENOMEM;
case 0xc000001c: return ENOSYS;
case 0xc000001e: return EACCES;
case 0xc000001f: return EACCES;
case 0xc0000021: return EACCES;
case 0xc0000022: return EACCES;
case 0xc0000024: return EINVAL;
case 0xc0000033: return EINVAL;
case 0xc0000034: return ENOENT;
case 0xc0000035: return EEXIST;
case 0xc0000037: return EINVAL;
case 0xc000003a: return ENOENT;
case 0xc0000040: return ENOMEM;
case 0xc0000041: return EACCES;
case 0xc0000042: return EINVAL;
case 0xc0000043: return EACCES;
case 0xc000004b: return EACCES;
case 0xc0000054: return ENOLCK;
case 0xc0000055: return ENOLCK;
case 0xc0000056: return EACCES;
case 0xc000007f: return ENOSPC;
case 0xc0000087: return ENOMEM;
case 0xc0000097: return ENOMEM;
case 0xc000009b: return ENOENT;
case 0xc000009e: return EAGAIN;
case 0xc00000a2: return EACCES;
case 0xc00000a3: return EAGAIN;
case 0xc00000af: return ENOSYS;
case 0xc00000ba: return EACCES;
case 0xc00000c0: return ENODEV;
case 0xc00000d4: return EXDEV;
case 0xc00000d5: return EACCES;
case 0xc00000fb: return ENOENT;
case 0xc0000101: return ENOTEMPTY;
case 0xc0000103: return EINVAL;
case 0xc0000107: return EBUSY;
case 0xc0000108: return EBUSY;
case 0xc000010a: return EACCES;
case 0xc000011f: return EMFILE;
case 0xc0000120: return ECANCELED;
case 0xc0000121: return EACCES;
case 0xc0000123: return EACCES;
case 0xc0000128: return EINVAL;
case 0xc0000189: return EACCES;
case 0xc00001ad: return ENOMEM;
case 0xc000022d: return EAGAIN;
case 0xc0000235: return EINVAL;
case 0xc000026e: return EAGAIN;
case 0xc000028a: return EACCES;
case 0xc000028b: return EACCES;
case 0xc000028d: return EACCES;
case 0xc000028e: return EACCES;
case 0xc000028f: return EACCES;
case 0xc0000290: return EACCES;
case 0xc000029c: return ENOSYS;
case 0xc00002c5: return EACCES;
case 0xc00002d3: return EAGAIN;
case 0xc00002ea: return EACCES;
case 0xc00002f0: return ENOENT;
case 0xc0000373: return ENOMEM;
case 0xc0000416: return ENOMEM;
case 0xc0000433: return EBUSY;
case 0xc0000434: return EBUSY;
case 0xc0000455: return EINVAL;
case 0xc0000467: return EACCES;
case 0xc0000491: return ENOENT;
case 0xc0000495: return EAGAIN;
case 0xc0000503: return EAGAIN;
case 0xc0000507: return EBUSY;
case 0xc0000512: return EACCES;
case 0xc000070a: return EINVAL;
case 0xc000070b: return EINVAL;
case 0xc000070c: return EINVAL;
case 0xc000070d: return EINVAL;
case 0xc000070e: return EINVAL;
case 0xc000070f: return EINVAL;
case 0xc0000710: return ENOSYS;
case 0xc0000711: return ENOSYS;
case 0xc0000716: return EINVAL;
case 0xc000071b: return ENOSYS;
case 0xc000071d: return ENOSYS;
case 0xc000071e: return ENOSYS;
case 0xc000071f: return ENOSYS;
case 0xc0000720: return ENOSYS;
case 0xc0000721: return ENOSYS;
case 0xc000080f: return EAGAIN;
case 0xc000a203: return EACCES;
}
return -1;
}
static win32::DWORD _nt_code_to_win32_code(win32::NTSTATUS c) // NOLINT
{
if(c >= 0)
{
return 0; // success
}
switch(static_cast<unsigned>(c))
{
case 0x80000002: return 0x3e6;
case 0x80000005: return 0xea;
case 0x80000006: return 0x12;
case 0x80000007: return 0x2a3;
case 0x8000000a: return 0x2a4;
case 0x8000000b: return 0x56f;
case 0x8000000c: return 0x2a8;
case 0x8000000d: return 0x12b;
case 0x8000000e: return 0x1c;
case 0x8000000f: return 0x15;
case 0x80000010: return 0x15;
case 0x80000011: return 0xaa;
case 0x80000012: return 0x103;
case 0x80000013: return 0xfe;
case 0x80000014: return 0xff;
case 0x80000015: return 0xff;
case 0x80000016: return 0x456;
case 0x80000017: return 0x2a5;
case 0x80000018: return 0x2a6;
case 0x8000001a: return 0x103;
case 0x8000001b: return 0x44d;
case 0x8000001c: return 0x456;
case 0x8000001d: return 0x457;
case 0x8000001e: return 0x44c;
case 0x8000001f: return 0x44e;
case 0x80000020: return 0x2a7;
case 0x80000021: return 0x44f;
case 0x80000022: return 0x450;
case 0x80000023: return 0x702;
case 0x80000024: return 0x713;
case 0x80000025: return 0x962;
case 0x80000026: return 0x2aa;
case 0x80000027: return 0x10f4;
case 0x80000028: return 0x2ab;
case 0x80000029: return 0x2ac;
case 0x8000002a: return 0x2ad;
case 0x8000002b: return 0x2ae;
case 0x8000002c: return 0x2af;
case 0x8000002d: return 0x2a9;
case 0x8000002e: return 0x321;
case 0x8000002f: return 0x324;
case 0x80000030: return 0xab;
case 0x80000032: return 0xeb;
case 0x80000288: return 0x48d;
case 0x80000289: return 0x48e;
case 0x80000803: return 0x1abb;
case 0x8000a127: return 0x3bdf;
case 0x8000cf00: return 0x16e;
case 0x8000cf04: return 0x16d;
case 0x8000cf05: return 0x176;
case 0x80130001: return 0x13c5;
case 0x80130002: return 0x13c6;
case 0x80130003: return 0x13c7;
case 0x80130004: return 0x13c8;
case 0x80130005: return 0x13c9;
case 0x80190009: return 0x19e5;
case 0x80190029: return 0x1aa0;
case 0x80190031: return 0x1aa2;
case 0x80190041: return 0x1ab3;
case 0x80190042: return 0x1ab4;
case 0x801c0001: return 0x7a;
case 0xc0000001: return 0x1f;
case 0xc0000002: return 0x1;
case 0xc0000003: return 0x57;
case 0xc0000004: return 0x18;
case 0xc0000005: return 0x3e6;
case 0xc0000006: return 0x3e7;
case 0xc0000007: return 0x5ae;
case 0xc0000008: return 0x6;
case 0xc0000009: return 0x3e9;
case 0xc000000a: return 0xc1;
case 0xc000000b: return 0x57;
case 0xc000000c: return 0x21d;
case 0xc000000d: return 0x57;
case 0xc000000e: return 0x2;
case 0xc000000f: return 0x2;
case 0xc0000010: return 0x1;
case 0xc0000011: return 0x26;
case 0xc0000012: return 0x22;
case 0xc0000013: return 0x15;
case 0xc0000014: return 0x6f9;
case 0xc0000015: return 0x1b;
case 0xc0000016: return 0xea;
case 0xc0000017: return 0x8;
case 0xc0000018: return 0x1e7;
case 0xc0000019: return 0x1e7;
case 0xc000001a: return 0x57;
case 0xc000001b: return 0x57;
case 0xc000001c: return 0x1;
case 0xc000001e: return 0x5;
case 0xc000001f: return 0x5;
case 0xc0000020: return 0xc1;
case 0xc0000021: return 0x5;
case 0xc0000022: return 0x5;
case 0xc0000023: return 0x7a;
case 0xc0000024: return 0x6;
case 0xc0000027: return 0x21e;
case 0xc0000028: return 0x21f;
case 0xc0000029: return 0x220;
case 0xc000002a: return 0x9e;
case 0xc000002c: return 0x1e7;
case 0xc000002d: return 0x1e7;
case 0xc000002e: return 0x221;
case 0xc000002f: return 0x222;
case 0xc0000030: return 0x57;
case 0xc0000031: return 0x223;
case 0xc0000032: return 0x571;
case 0xc0000033: return 0x7b;
case 0xc0000034: return 0x2;
case 0xc0000035: return 0xb7;
case 0xc0000036: return 0x72a;
case 0xc0000037: return 0x6;
case 0xc0000038: return 0x224;
case 0xc0000039: return 0xa1;
case 0xc000003a: return 0x3;
case 0xc000003b: return 0xa1;
case 0xc000003c: return 0x45d;
case 0xc000003d: return 0x45d;
case 0xc000003e: return 0x17;
case 0xc000003f: return 0x17;
case 0xc0000040: return 0x8;
case 0xc0000041: return 0x5;
case 0xc0000042: return 0x6;
case 0xc0000043: return 0x20;
case 0xc0000044: return 0x718;
case 0xc0000045: return 0x57;
case 0xc0000046: return 0x120;
case 0xc0000047: return 0x12a;
case 0xc0000048: return 0x57;
case 0xc0000049: return 0x57;
case 0xc000004a: return 0x9c;
case 0xc000004b: return 0x5;
case 0xc000004c: return 0x57;
case 0xc000004d: return 0x57;
case 0xc000004e: return 0x57;
case 0xc000004f: return 0x11a;
case 0xc0000050: return 0xff;
case 0xc0000051: return 0x570;
case 0xc0000052: return 0x570;
case 0xc0000053: return 0x570;
case 0xc0000054: return 0x21;
case 0xc0000055: return 0x21;
case 0xc0000056: return 0x5;
case 0xc0000057: return 0x32;
case 0xc0000058: return 0x519;
case 0xc0000059: return 0x51a;
case 0xc000005a: return 0x51b;
case 0xc000005b: return 0x51c;
case 0xc000005c: return 0x51d;
case 0xc000005d: return 0x51e;
case 0xc000005e: return 0x51f;
case 0xc000005f: return 0x520;
case 0xc0000060: return 0x521;
case 0xc0000061: return 0x522;
case 0xc0000062: return 0x523;
case 0xc0000063: return 0x524;
case 0xc0000064: return 0x525;
case 0xc0000065: return 0x526;
case 0xc0000066: return 0x527;
case 0xc0000067: return 0x528;
case 0xc0000068: return 0x529;
case 0xc0000069: return 0x52a;
case 0xc000006a: return 0x56;
case 0xc000006b: return 0x52c;
case 0xc000006c: return 0x52d;
case 0xc000006d: return 0x52e;
case 0xc000006e: return 0x52f;
case 0xc000006f: return 0x530;
case 0xc0000070: return 0x531;
case 0xc0000071: return 0x532;
case 0xc0000072: return 0x533;
case 0xc0000073: return 0x534;
case 0xc0000074: return 0x535;
case 0xc0000075: return 0x536;
case 0xc0000076: return 0x537;
case 0xc0000077: return 0x538;
case 0xc0000078: return 0x539;
case 0xc0000079: return 0x53a;
case 0xc000007a: return 0x7f;
case 0xc000007b: return 0xc1;
case 0xc000007c: return 0x3f0;
case 0xc000007d: return 0x53c;
case 0xc000007e: return 0x9e;
case 0xc000007f: return 0x70;
case 0xc0000080: return 0x53d;
case 0xc0000081: return 0x53e;
case 0xc0000082: return 0x44;
case 0xc0000083: return 0x103;
case 0xc0000084: return 0x53f;
case 0xc0000085: return 0x103;
case 0xc0000086: return 0x9a;
case 0xc0000087: return 0xe;
case 0xc0000088: return 0x1e7;
case 0xc0000089: return 0x714;
case 0xc000008a: return 0x715;
case 0xc000008b: return 0x716;
case 0xc0000095: return 0x216;
case 0xc0000097: return 0x8;
case 0xc0000098: return 0x3ee;
case 0xc0000099: return 0x540;
case 0xc000009a: return 0x5aa;
case 0xc000009b: return 0x3;
case 0xc000009c: return 0x17;
case 0xc000009d: return 0x48f;
case 0xc000009e: return 0x15;
case 0xc000009f: return 0x1e7;
case 0xc00000a0: return 0x1e7;
case 0xc00000a1: return 0x5ad;
case 0xc00000a2: return 0x13;
case 0xc00000a3: return 0x15;
case 0xc00000a4: return 0x541;
case 0xc00000a5: return 0x542;
case 0xc00000a6: return 0x543;
case 0xc00000a7: return 0x544;
case 0xc00000a8: return 0x545;
case 0xc00000a9: return 0x57;
case 0xc00000aa: return 0x225;
case 0xc00000ab: return 0xe7;
case 0xc00000ac: return 0xe7;
case 0xc00000ad: return 0xe6;
case 0xc00000ae: return 0xe7;
case 0xc00000af: return 0x1;
case 0xc00000b0: return 0xe9;
case 0xc00000b1: return 0xe8;
case 0xc00000b2: return 0x217;
case 0xc00000b3: return 0x218;
case 0xc00000b4: return 0xe6;
case 0xc00000b5: return 0x79;
case 0xc00000b6: return 0x26;
case 0xc00000b7: return 0x226;
case 0xc00000b8: return 0x227;
case 0xc00000b9: return 0x228;
case 0xc00000ba: return 0x5;
case 0xc00000bb: return 0x32;
case 0xc00000bc: return 0x33;
case 0xc00000bd: return 0x34;
case 0xc00000be: return 0x35;
case 0xc00000bf: return 0x36;
case 0xc00000c0: return 0x37;
case 0xc00000c1: return 0x38;
case 0xc00000c2: return 0x39;
case 0xc00000c3: return 0x3a;
case 0xc00000c4: return 0x3b;
case 0xc00000c5: return 0x3c;
case 0xc00000c6: return 0x3d;
case 0xc00000c7: return 0x3e;
case 0xc00000c8: return 0x3f;
case 0xc00000c9: return 0x40;
case 0xc00000ca: return 0x41;
case 0xc00000cb: return 0x42;
case 0xc00000cc: return 0x43;
case 0xc00000cd: return 0x44;
case 0xc00000ce: return 0x45;
case 0xc00000cf: return 0x46;
case 0xc00000d0: return 0x47;
case 0xc00000d1: return 0x48;
case 0xc00000d2: return 0x58;
case 0xc00000d3: return 0x229;
case 0xc00000d4: return 0x11;
case 0xc00000d5: return 0x5;
case 0xc00000d6: return 0xf0;
case 0xc00000d7: return 0x546;
case 0xc00000d8: return 0x22a;
case 0xc00000d9: return 0xe8;
case 0xc00000da: return 0x547;
case 0xc00000db: return 0x22b;
case 0xc00000dc: return 0x548;
case 0xc00000dd: return 0x549;
case 0xc00000de: return 0x54a;
case 0xc00000df: return 0x54b;
case 0xc00000e0: return 0x54c;
case 0xc00000e1: return 0x54d;
case 0xc00000e2: return 0x12c;
case 0xc00000e3: return 0x12d;
case 0xc00000e4: return 0x54e;
case 0xc00000e5: return 0x54f;
case 0xc00000e6: return 0x550;
case 0xc00000e7: return 0x551;
case 0xc00000e8: return 0x6f8;
case 0xc00000e9: return 0x45d;
case 0xc00000ea: return 0x22c;
case 0xc00000eb: return 0x22d;
case 0xc00000ec: return 0x22e;
case 0xc00000ed: return 0x552;
case 0xc00000ee: return 0x553;
case 0xc00000ef: return 0x57;
case 0xc00000f0: return 0x57;
case 0xc00000f1: return 0x57;
case 0xc00000f2: return 0x57;
case 0xc00000f3: return 0x57;
case 0xc00000f4: return 0x57;
case 0xc00000f5: return 0x57;
case 0xc00000f6: return 0x57;
case 0xc00000f7: return 0x57;
case 0xc00000f8: return 0x57;
case 0xc00000f9: return 0x57;
case 0xc00000fa: return 0x57;
case 0xc00000fb: return 0x3;
case 0xc00000fc: return 0x420;
case 0xc00000fd: return 0x3e9;
case 0xc00000fe: return 0x554;
case 0xc00000ff: return 0x22f;
case 0xc0000100: return 0xcb;
case 0xc0000101: return 0x91;
case 0xc0000102: return 0x570;
case 0xc0000103: return 0x10b;
case 0xc0000104: return 0x555;
case 0xc0000105: return 0x556;
case 0xc0000106: return 0xce;
case 0xc0000107: return 0x961;
case 0xc0000108: return 0x964;
case 0xc000010a: return 0x5;
case 0xc000010b: return 0x557;
case 0xc000010c: return 0x230;
case 0xc000010d: return 0x558;
case 0xc000010e: return 0x420;
case 0xc000010f: return 0x21a;
case 0xc0000110: return 0x21a;
case 0xc0000111: return 0x21a;
case 0xc0000112: return 0x21a;
case 0xc0000113: return 0x21a;
case 0xc0000114: return 0x21a;
case 0xc0000115: return 0x21a;
case 0xc0000116: return 0x21a;
case 0xc0000117: return 0x5a4;
case 0xc0000118: return 0x231;
case 0xc0000119: return 0x233;
case 0xc000011a: return 0x234;
case 0xc000011b: return 0xc1;
case 0xc000011c: return 0x559;
case 0xc000011d: return 0x55a;
case 0xc000011e: return 0x3ee;
case 0xc000011f: return 0x4;
case 0xc0000120: return 0x3e3;
case 0xc0000121: return 0x5;
case 0xc0000122: return 0x4ba;
case 0xc0000123: return 0x5;
case 0xc0000124: return 0x55b;
case 0xc0000125: return 0x55c;
case 0xc0000126: return 0x55d;
case 0xc0000127: return 0x55e;
case 0xc0000128: return 0x6;
case 0xc0000129: return 0x235;
case 0xc000012a: return 0x236;
case 0xc000012b: return 0x55f;
case 0xc000012c: return 0x237;
case 0xc000012d: return 0x5af;
case 0xc000012e: return 0xc1;
case 0xc000012f: return 0xc1;
case 0xc0000130: return 0xc1;
case 0xc0000131: return 0xc1;
case 0xc0000132: return 0x238;
case 0xc0000133: return 0x576;
case 0xc0000134: return 0x239;
case 0xc0000135: return 0x7e;
case 0xc0000136: return 0x23a;
case 0xc0000137: return 0x23b;
case 0xc0000138: return 0xb6;
case 0xc0000139: return 0x7f;
case 0xc000013a: return 0x23c;
case 0xc000013b: return 0x40;
case 0xc000013c: return 0x40;
case 0xc000013d: return 0x33;
case 0xc000013e: return 0x3b;
case 0xc000013f: return 0x3b;
case 0xc0000140: return 0x3b;
case 0xc0000141: return 0x3b;
case 0xc0000142: return 0x45a;
case 0xc0000143: return 0x23d;
case 0xc0000144: return 0x23e;
case 0xc0000145: return 0x23f;
case 0xc0000146: return 0x240;
case 0xc0000147: return 0x242;
case 0xc0000148: return 0x7c;
case 0xc0000149: return 0x56;
case 0xc000014a: return 0x243;
case 0xc000014b: return 0x6d;
case 0xc000014c: return 0x3f1;
case 0xc000014d: return 0x3f8;
case 0xc000014e: return 0x244;
case 0xc000014f: return 0x3ed;
case 0xc0000150: return 0x45e;
case 0xc0000151: return 0x560;
case 0xc0000152: return 0x561;
case 0xc0000153: return 0x562;
case 0xc0000154: return 0x563;
case 0xc0000155: return 0x564;
case 0xc0000156: return 0x565;
case 0xc0000157: return 0x566;
case 0xc0000158: return 0x567;
case 0xc0000159: return 0x3ef;
case 0xc000015a: return 0x568;
case 0xc000015b: return 0x569;
case 0xc000015c: return 0x3f9;
case 0xc000015d: return 0x56a;
case 0xc000015e: return 0x245;
case 0xc000015f: return 0x45d;
case 0xc0000160: return 0x4db;
case 0xc0000161: return 0x246;
case 0xc0000162: return 0x459;
case 0xc0000163: return 0x247;
case 0xc0000164: return 0x248;
case 0xc0000165: return 0x462;
case 0xc0000166: return 0x463;
case 0xc0000167: return 0x464;
case 0xc0000168: return 0x465;
case 0xc0000169: return 0x466;
case 0xc000016a: return 0x467;
case 0xc000016b: return 0x468;
case 0xc000016c: return 0x45f;
case 0xc000016d: return 0x45d;
case 0xc000016e: return 0x249;
case 0xc0000172: return 0x451;
case 0xc0000173: return 0x452;
case 0xc0000174: return 0x453;
case 0xc0000175: return 0x454;
case 0xc0000176: return 0x455;
case 0xc0000177: return 0x469;
case 0xc0000178: return 0x458;
case 0xc000017a: return 0x56b;
case 0xc000017b: return 0x56c;
case 0xc000017c: return 0x3fa;
case 0xc000017d: return 0x3fb;
case 0xc000017e: return 0x56d;
case 0xc000017f: return 0x56e;
case 0xc0000180: return 0x3fc;
case 0xc0000181: return 0x3fd;
case 0xc0000182: return 0x57;
case 0xc0000183: return 0x45d;
case 0xc0000184: return 0x16;
case 0xc0000185: return 0x45d;
case 0xc0000186: return 0x45d;
case 0xc0000187: return 0x24a;
case 0xc0000188: return 0x5de;
case 0xc0000189: return 0x13;
case 0xc000018a: return 0x6fa;
case 0xc000018b: return 0x6fb;
case 0xc000018c: return 0x6fc;
case 0xc000018d: return 0x6fd;
case 0xc000018e: return 0x5dc;
case 0xc000018f: return 0x5dd;
case 0xc0000190: return 0x6fe;
case 0xc0000191: return 0x24b;
case 0xc0000192: return 0x700;
case 0xc0000193: return 0x701;
case 0xc0000194: return 0x46b;
case 0xc0000195: return 0x4c3;
case 0xc0000196: return 0x4c4;
case 0xc0000197: return 0x5df;
case 0xc0000198: return 0x70f;
case 0xc0000199: return 0x710;
case 0xc000019a: return 0x711;
case 0xc000019b: return 0x712;
case 0xc000019c: return 0x24c;
case 0xc000019d: return 0x420;
case 0xc000019e: return 0x130;
case 0xc000019f: return 0x131;
case 0xc00001a0: return 0x132;
case 0xc00001a1: return 0x133;
case 0xc00001a2: return 0x325;
case 0xc00001a3: return 0x134;
case 0xc00001a4: return 0x135;
case 0xc00001a5: return 0x136;
case 0xc00001a6: return 0x137;
case 0xc00001a7: return 0x139;
case 0xc00001a8: return 0x1abb;
case 0xc00001a9: return 0x32;
case 0xc00001aa: return 0x3d54;
case 0xc00001ab: return 0x329;
case 0xc00001ac: return 0x678;
case 0xc00001ad: return 0x8;
case 0xc00001ae: return 0x2f7;
case 0xc00001af: return 0x32d;
case 0xc0000201: return 0x41;
case 0xc0000202: return 0x572;
case 0xc0000203: return 0x3b;
case 0xc0000204: return 0x717;
case 0xc0000205: return 0x46a;
case 0xc0000206: return 0x6f8;
case 0xc0000207: return 0x4be;
case 0xc0000208: return 0x4be;
case 0xc0000209: return 0x44;
case 0xc000020a: return 0x34;
case 0xc000020b: return 0x40;
case 0xc000020c: return 0x40;
case 0xc000020d: return 0x40;
case 0xc000020e: return 0x44;
case 0xc000020f: return 0x3b;
case 0xc0000210: return 0x3b;
case 0xc0000211: return 0x3b;
case 0xc0000212: return 0x3b;
case 0xc0000213: return 0x3b;
case 0xc0000214: return 0x3b;
case 0xc0000215: return 0x3b;
case 0xc0000216: return 0x32;
case 0xc0000217: return 0x32;
case 0xc0000218: return 0x24d;
case 0xc0000219: return 0x24e;
case 0xc000021a: return 0x24f;
case 0xc000021b: return 0x250;
case 0xc000021c: return 0x17e6;
case 0xc000021d: return 0x251;
case 0xc000021e: return 0x252;
case 0xc000021f: return 0x253;
case 0xc0000220: return 0x46c;
case 0xc0000221: return 0xc1;
case 0xc0000222: return 0x254;
case 0xc0000223: return 0x255;
case 0xc0000224: return 0x773;
case 0xc0000225: return 0x490;
case 0xc0000226: return 0x256;
case 0xc0000227: return 0x4ff;
case 0xc0000228: return 0x257;
case 0xc0000229: return 0x57;
case 0xc000022a: return 0x1392;
case 0xc000022b: return 0x1392;
case 0xc000022c: return 0x258;
case 0xc000022d: return 0x4d5;
case 0xc000022e: return 0x259;
case 0xc000022f: return 0x25a;
case 0xc0000230: return 0x492;
case 0xc0000231: return 0x25b;
case 0xc0000232: return 0x25c;
case 0xc0000233: return 0x774;
case 0xc0000234: return 0x775;
case 0xc0000235: return 0x6;
case 0xc0000236: return 0x4c9;
case 0xc0000237: return 0x4ca;
case 0xc0000238: return 0x4cb;
case 0xc0000239: return 0x4cc;
case 0xc000023a: return 0x4cd;
case 0xc000023b: return 0x4ce;
case 0xc000023c: return 0x4cf;
case 0xc000023d: return 0x4d0;
case 0xc000023e: return 0x4d1;
case 0xc000023f: return 0x4d2;
case 0xc0000240: return 0x4d3;
case 0xc0000241: return 0x4d4;
case 0xc0000242: return 0x25d;
case 0xc0000243: return 0x4c8;
case 0xc0000244: return 0x25e;
case 0xc0000245: return 0x25f;
case 0xc0000246: return 0x4d6;
case 0xc0000247: return 0x4d7;
case 0xc0000248: return 0x4d8;
case 0xc0000249: return 0xc1;
case 0xc0000250: return 0x260;
case 0xc0000251: return 0x261;
case 0xc0000252: return 0x262;
case 0xc0000253: return 0x4d4;
case 0xc0000254: return 0x263;
case 0xc0000255: return 0x264;
case 0xc0000256: return 0x265;
case 0xc0000257: return 0x4d0;
case 0xc0000258: return 0x266;
case 0xc0000259: return 0x573;
case 0xc000025a: return 0x267;
case 0xc000025b: return 0x268;
case 0xc000025c: return 0x269;
case 0xc000025e: return 0x422;
case 0xc000025f: return 0x26a;
case 0xc0000260: return 0x26b;
case 0xc0000261: return 0x26c;
case 0xc0000262: return 0xb6;
case 0xc0000263: return 0x7f;
case 0xc0000264: return 0x120;
case 0xc0000265: return 0x476;
case 0xc0000266: return 0x26d;
case 0xc0000267: return 0x10fe;
case 0xc0000268: return 0x26e;
case 0xc0000269: return 0x26f;
case 0xc000026a: return 0x1b8e;
case 0xc000026b: return 0x270;
case 0xc000026c: return 0x7d1;
case 0xc000026d: return 0x4b1;
case 0xc000026e: return 0x15;
case 0xc000026f: return 0x21c;
case 0xc0000270: return 0x21c;
case 0xc0000271: return 0x271;
case 0xc0000272: return 0x491;
case 0xc0000273: return 0x272;
case 0xc0000275: return 0x1126;
case 0xc0000276: return 0x1129;
case 0xc0000277: return 0x112a;
case 0xc0000278: return 0x1128;
case 0xc0000279: return 0x780;
case 0xc000027a: return 0x291;
case 0xc000027b: return 0x54f;
case 0xc000027c: return 0x54f;
case 0xc0000280: return 0x781;
case 0xc0000281: return 0xa1;
case 0xc0000282: return 0x273;
case 0xc0000283: return 0x488;
case 0xc0000284: return 0x489;
case 0xc0000285: return 0x48a;
case 0xc0000286: return 0x48b;
case 0xc0000287: return 0x48c;
case 0xc000028a: return 0x5;
case 0xc000028b: return 0x5;
case 0xc000028c: return 0x284;
case 0xc000028d: return 0x5;
case 0xc000028e: return 0x5;
case 0xc000028f: return 0x5;
case 0xc0000290: return 0x5;
case 0xc0000291: return 0x1777;
case 0xc0000292: return 0x1778;
case 0xc0000293: return 0x1772;
case 0xc0000295: return 0x1068;
case 0xc0000296: return 0x1069;
case 0xc0000297: return 0x106a;
case 0xc0000298: return 0x106b;
case 0xc0000299: return 0x201a;
case 0xc000029a: return 0x201b;
case 0xc000029b: return 0x201c;
case 0xc000029c: return 0x1;
case 0xc000029d: return 0x10ff;
case 0xc000029e: return 0x1100;
case 0xc000029f: return 0x494;
case 0xc00002a0: return 0x274;
case 0xc00002a1: return 0x200a;
case 0xc00002a2: return 0x200b;
case 0xc00002a3: return 0x200c;
case 0xc00002a4: return 0x200d;
case 0xc00002a5: return 0x200e;
case 0xc00002a6: return 0x200f;
case 0xc00002a7: return 0x2010;
case 0xc00002a8: return 0x2011;
case 0xc00002a9: return 0x2012;
case 0xc00002aa: return 0x2013;
case 0xc00002ab: return 0x2014;
case 0xc00002ac: return 0x2015;
case 0xc00002ad: return 0x2016;
case 0xc00002ae: return 0x2017;
case 0xc00002af: return 0x2018;
case 0xc00002b0: return 0x2019;
case 0xc00002b1: return 0x211e;
case 0xc00002b2: return 0x1127;
case 0xc00002b3: return 0x275;
case 0xc00002b4: return 0x276;
case 0xc00002b5: return 0x277;
case 0xc00002b6: return 0x651;
case 0xc00002b7: return 0x49a;
case 0xc00002b8: return 0x49b;
case 0xc00002b9: return 0x278;
case 0xc00002ba: return 0x2047;
case 0xc00002c1: return 0x2024;
case 0xc00002c2: return 0x279;
case 0xc00002c3: return 0x575;
case 0xc00002c4: return 0x27a;
case 0xc00002c5: return 0x3e6;
case 0xc00002c6: return 0x1075;
case 0xc00002c7: return 0x1076;
case 0xc00002c8: return 0x27b;
case 0xc00002c9: return 0x4ed;
case 0xc00002ca: return 0x10e8;
case 0xc00002cb: return 0x2138;
case 0xc00002cc: return 0x4e3;
case 0xc00002cd: return 0x2139;
case 0xc00002ce: return 0x27c;
case 0xc00002cf: return 0x49d;
case 0xc00002d0: return 0x213a;
case 0xc00002d1: return 0x27d;
case 0xc00002d2: return 0x27e;
case 0xc00002d3: return 0x15;
case 0xc00002d4: return 0x2141;
case 0xc00002d5: return 0x2142;
case 0xc00002d6: return 0x2143;
case 0xc00002d7: return 0x2144;
case 0xc00002d8: return 0x2145;
case 0xc00002d9: return 0x2146;
case 0xc00002da: return 0x2147;
case 0xc00002db: return 0x2148;
case 0xc00002dc: return 0x2149;
case 0xc00002dd: return 0x32;
case 0xc00002de: return 0x27f;
case 0xc00002df: return 0x2151;
case 0xc00002e0: return 0x2152;
case 0xc00002e1: return 0x2153;
case 0xc00002e2: return 0x2154;
case 0xc00002e3: return 0x215d;
case 0xc00002e4: return 0x2163;
case 0xc00002e5: return 0x2164;
case 0xc00002e6: return 0x2165;
case 0xc00002e7: return 0x216d;
case 0xc00002e8: return 0x280;
case 0xc00002e9: return 0x577;
case 0xc00002ea: return 0x52;
case 0xc00002eb: return 0x281;
case 0xc00002ec: return 0x2171;
case 0xc00002ed: return 0x2172;
case 0xc00002f0: return 0x2;
case 0xc00002fe: return 0x45b;
case 0xc00002ff: return 0x4e7;
case 0xc0000300: return 0x4e6;
case 0xc0000301: return 0x106f;
case 0xc0000302: return 0x1074;
case 0xc0000303: return 0x106e;
case 0xc0000304: return 0x12e;
case 0xc000030c: return 0x792;
case 0xc000030d: return 0x793;
case 0xc0000320: return 0x4ef;
case 0xc0000321: return 0x4f0;
case 0xc0000350: return 0x4e8;
case 0xc0000352: return 0x177d;
case 0xc0000353: return 0x282;
case 0xc0000354: return 0x504;
case 0xc0000355: return 0x283;
case 0xc0000357: return 0x217c;
case 0xc0000358: return 0x2182;
case 0xc0000359: return 0xc1;
case 0xc000035a: return 0xc1;
case 0xc000035c: return 0x572;
case 0xc000035d: return 0x4eb;
case 0xc000035f: return 0x286;
case 0xc0000361: return 0x4ec;
case 0xc0000362: return 0x4ec;
case 0xc0000363: return 0x4ec;
case 0xc0000364: return 0x4ec;
case 0xc0000365: return 0x287;
case 0xc0000366: return 0x288;
case 0xc0000368: return 0x289;
case 0xc0000369: return 0x28a;
case 0xc000036a: return 0x28b;
case 0xc000036b: return 0x4fb;
case 0xc000036c: return 0x4fb;
case 0xc000036d: return 0x28c;
case 0xc000036e: return 0x28d;
case 0xc000036f: return 0x4fc;
case 0xc0000371: return 0x21ac;
case 0xc0000372: return 0x312;
case 0xc0000373: return 0x8;
case 0xc0000374: return 0x54f;
case 0xc0000388: return 0x4f1;
case 0xc000038e: return 0x28e;
case 0xc0000401: return 0x78c;
case 0xc0000402: return 0x78d;
case 0xc0000403: return 0x78e;
case 0xc0000404: return 0x217b;
case 0xc0000405: return 0x219d;
case 0xc0000406: return 0x219f;
case 0xc0000407: return 0x28f;
case 0xc0000408: return 0x52e;
case 0xc0000409: return 0x502;
case 0xc0000410: return 0x503;
case 0xc0000411: return 0x290;
case 0xc0000412: return 0x505;
case 0xc0000413: return 0x78f;
case 0xc0000414: return 0x506;
case 0xc0000416: return 0x8;
case 0xc0000417: return 0x508;
case 0xc0000418: return 0x791;
case 0xc0000419: return 0x215b;
case 0xc000041a: return 0x21ba;
case 0xc000041b: return 0x21bb;
case 0xc000041c: return 0x21bc;
case 0xc000041d: return 0x2c9;
case 0xc0000420: return 0x29c;
case 0xc0000421: return 0x219;
case 0xc0000423: return 0x300;
case 0xc0000424: return 0x4fb;
case 0xc0000425: return 0x3fa;
case 0xc0000426: return 0x301;
case 0xc0000427: return 0x299;
case 0xc0000428: return 0x241;
case 0xc0000429: return 0x307;
case 0xc000042a: return 0x308;
case 0xc000042b: return 0x50c;
case 0xc000042c: return 0x2e4;
case 0xc0000432: return 0x509;
case 0xc0000433: return 0xaa;
case 0xc0000434: return 0xaa;
case 0xc0000435: return 0x4c8;
case 0xc0000441: return 0x1781;
case 0xc0000442: return 0x1782;
case 0xc0000443: return 0x1783;
case 0xc0000444: return 0x1784;
case 0xc0000445: return 0x1785;
case 0xc0000446: return 0x513;
case 0xc0000450: return 0x50b;
case 0xc0000451: return 0x3b92;
case 0xc0000452: return 0x3bc3;
case 0xc0000453: return 0x5bb;
case 0xc0000454: return 0x5be;
case 0xc0000455: return 0x6;
case 0xc0000456: return 0x57;
case 0xc0000457: return 0x57;
case 0xc0000458: return 0x57;
case 0xc0000459: return 0xbea;
case 0xc0000460: return 0x138;
case 0xc0000461: return 0x13a;
case 0xc0000462: return 0x3cfc;
case 0xc0000463: return 0x13c;
case 0xc0000464: return 0x141;
case 0xc0000465: return 0x13b;
case 0xc0000466: return 0x40;
case 0xc0000467: return 0x20;
case 0xc0000468: return 0x142;
case 0xc0000469: return 0x3d00;
case 0xc000046a: return 0x151;
case 0xc000046b: return 0x152;
case 0xc000046c: return 0x153;
case 0xc000046d: return 0x156;
case 0xc000046e: return 0x157;
case 0xc000046f: return 0x158;
case 0xc0000470: return 0x143;
case 0xc0000471: return 0x144;
case 0xc0000472: return 0x146;
case 0xc0000473: return 0x14b;
case 0xc0000474: return 0x147;
case 0xc0000475: return 0x148;
case 0xc0000476: return 0x149;
case 0xc0000477: return 0x14a;
case 0xc0000478: return 0x14c;
case 0xc0000479: return 0x14d;
case 0xc000047a: return 0x14e;
case 0xc000047b: return 0x14f;
case 0xc000047c: return 0x150;
case 0xc000047d: return 0x5b4;
case 0xc000047e: return 0x3d07;
case 0xc000047f: return 0x3d08;
case 0xc0000480: return 0x40;
case 0xc0000481: return 0x7e;
case 0xc0000482: return 0x7e;
case 0xc0000483: return 0x1e3;
case 0xc0000486: return 0x159;
case 0xc0000487: return 0x1f;
case 0xc0000488: return 0x15a;
case 0xc0000489: return 0x3d0f;
case 0xc000048a: return 0x32a;
case 0xc000048b: return 0x32c;
case 0xc000048c: return 0x15b;
case 0xc000048d: return 0x15c;
case 0xc000048e: return 0x162;
case 0xc000048f: return 0x15d;
case 0xc0000490: return 0x491;
case 0xc0000491: return 0x2;
case 0xc0000492: return 0x490;
case 0xc0000493: return 0x492;
case 0xc0000494: return 0x307;
case 0xc0000495: return 0x15;
case 0xc0000496: return 0x163;
case 0xc0000497: return 0x3d5a;
case 0xc0000499: return 0x167;
case 0xc000049a: return 0x168;
case 0xc000049b: return 0x12e;
case 0xc000049c: return 0x169;
case 0xc000049d: return 0x16f;
case 0xc000049e: return 0x170;
case 0xc000049f: return 0x49f;
case 0xc00004a0: return 0x4a0;
case 0xc00004a1: return 0x18f;
case 0xc0000500: return 0x60e;
case 0xc0000501: return 0x60f;
case 0xc0000502: return 0x610;
case 0xc0000503: return 0x15;
case 0xc0000504: return 0x13f;
case 0xc0000505: return 0x140;
case 0xc0000506: return 0x5bf;
case 0xc0000507: return 0xaa;
case 0xc0000508: return 0x5e0;
case 0xc0000509: return 0x5e1;
case 0xc000050b: return 0x112b;
case 0xc000050e: return 0x115c;
case 0xc000050f: return 0x10d3;
case 0xc0000510: return 0x4df;
case 0xc0000511: return 0x32e;
case 0xc0000512: return 0x5;
case 0xc0000513: return 0x180;
case 0xc0000514: return 0x115d;
case 0xc0000602: return 0x675;
case 0xc0000604: return 0x677;
case 0xc0000606: return 0x679;
case 0xc000060a: return 0x67c;
case 0xc000060b: return 0x67d;
case 0xc0000700: return 0x54f;
case 0xc0000701: return 0x54f;
case 0xc0000702: return 0x57;
case 0xc0000703: return 0x54f;
case 0xc0000704: return 0x32;
case 0xc0000705: return 0x57;
case 0xc0000706: return 0x57;
case 0xc0000707: return 0x32;
case 0xc0000708: return 0x54f;
case 0xc0000709: return 0x30b;
case 0xc000070a: return 0x6;
case 0xc000070b: return 0x6;
case 0xc000070c: return 0x6;
case 0xc000070d: return 0x6;
case 0xc000070e: return 0x6;
case 0xc000070f: return 0x6;
case 0xc0000710: return 0x1;
case 0xc0000711: return 0x1;
case 0xc0000712: return 0x50d;
case 0xc0000713: return 0x310;
case 0xc0000714: return 0x52e;
case 0xc0000715: return 0x5b7;
case 0xc0000716: return 0x7b;
case 0xc0000717: return 0x459;
case 0xc0000718: return 0x54f;
case 0xc0000719: return 0x54f;
case 0xc000071a: return 0x54f;
case 0xc000071b: return 0x1;
case 0xc000071c: return 0x57;
case 0xc000071d: return 0x1;
case 0xc000071e: return 0x1;
case 0xc000071f: return 0x1;
case 0xc0000720: return 0x1;
case 0xc0000721: return 0x1;
case 0xc0000722: return 0x72b;
case 0xc0000723: return 0x1f;
case 0xc0000724: return 0x1f;
case 0xc0000725: return 0x1f;
case 0xc0000726: return 0x1f;
case 0xc0000800: return 0x30c;
case 0xc0000801: return 0x21a4;
case 0xc0000802: return 0x50f;
case 0xc0000804: return 0x510;
case 0xc0000805: return 0x1ac1;
case 0xc0000806: return 0x1ac3;
case 0xc0000808: return 0x319;
case 0xc0000809: return 0x31a;
case 0xc000080a: return 0x31b;
case 0xc000080b: return 0x31c;
case 0xc000080c: return 0x31d;
case 0xc000080d: return 0x31e;
case 0xc000080e: return 0x31f;
case 0xc000080f: return 0x4d5;
case 0xc0000810: return 0x328;
case 0xc0000811: return 0x54f;
case 0xc0000901: return 0xdc;
case 0xc0000902: return 0xdd;
case 0xc0000903: return 0xde;
case 0xc0000904: return 0xdf;
case 0xc0000905: return 0xe0;
case 0xc0000906: return 0xe1;
case 0xc0000907: return 0xe2;
case 0xc0000908: return 0x317;
case 0xc0000909: return 0x322;
case 0xc0000910: return 0x326;
case 0xc0009898: return 0x29e;
case 0xc000a002: return 0x17;
case 0xc000a003: return 0x139f;
case 0xc000a004: return 0x154;
case 0xc000a005: return 0x155;
case 0xc000a006: return 0x32b;
case 0xc000a007: return 0x32;
case 0xc000a010: return 0xea;
case 0xc000a011: return 0xea;
case 0xc000a012: return 0x4d0;
case 0xc000a013: return 0x32;
case 0xc000a014: return 0x4d1;
case 0xc000a080: return 0x314;
case 0xc000a081: return 0x315;
case 0xc000a082: return 0x316;
case 0xc000a083: return 0x5b9;
case 0xc000a084: return 0x5ba;
case 0xc000a085: return 0x5bc;
case 0xc000a086: return 0x5bd;
case 0xc000a087: return 0x21bd;
case 0xc000a088: return 0x21be;
case 0xc000a089: return 0x21c6;
case 0xc000a100: return 0x3bc4;
case 0xc000a101: return 0x3bc5;
case 0xc000a121: return 0x3bd9;
case 0xc000a122: return 0x3bda;
case 0xc000a123: return 0x3bdb;
case 0xc000a124: return 0x3bdc;
case 0xc000a125: return 0x3bdd;
case 0xc000a126: return 0x3bde;
case 0xc000a141: return 0x3c28;
case 0xc000a142: return 0x3c29;
case 0xc000a143: return 0x3c2a;
case 0xc000a145: return 0x3c2b;
case 0xc000a146: return 0x3c2c;
case 0xc000a200: return 0x109a;
case 0xc000a201: return 0x109c;
case 0xc000a202: return 0x109d;
case 0xc000a203: return 0x5;
case 0xc000a281: return 0x1130;
case 0xc000a282: return 0x1131;
case 0xc000a283: return 0x1132;
case 0xc000a284: return 0x1133;
case 0xc000a285: return 0x1134;
case 0xc000a2a1: return 0x1158;
case 0xc000a2a2: return 0x1159;
case 0xc000a2a3: return 0x115a;
case 0xc000a2a4: return 0x115b;
case 0xc000ce01: return 0x171;
case 0xc000ce02: return 0x172;
case 0xc000ce03: return 0x173;
case 0xc000ce04: return 0x174;
case 0xc000ce05: return 0x181;
case 0xc000cf00: return 0x166;
case 0xc000cf01: return 0x16a;
case 0xc000cf02: return 0x16b;
case 0xc000cf03: return 0x16c;
case 0xc000cf06: return 0x177;
case 0xc000cf07: return 0x178;
case 0xc000cf08: return 0x179;
case 0xc000cf09: return 0x17a;
case 0xc000cf0a: return 0x17b;
case 0xc000cf0b: return 0x17c;
case 0xc000cf0c: return 0x17d;
case 0xc000cf0d: return 0x17e;
case 0xc000cf0e: return 0x17f;
case 0xc000cf0f: return 0x182;
case 0xc000cf10: return 0x183;
case 0xc000cf11: return 0x184;
case 0xc000cf12: return 0x185;
case 0xc000cf13: return 0x186;
case 0xc000cf14: return 0x187;
case 0xc000cf15: return 0x188;
case 0xc000cf16: return 0x189;
case 0xc000cf17: return 0x18a;
case 0xc000cf18: return 0x18b;
case 0xc000cf19: return 0x18c;
case 0xc000cf1a: return 0x18d;
case 0xc000cf1b: return 0x18e;
}
return static_cast<win32::DWORD>(-1);
}
//! Construct from a NT error code
static _base::string_ref _make_string_ref(win32::NTSTATUS c) noexcept
{
wchar_t buffer[32768];
static win32::HMODULE ntdll = win32::GetModuleHandleW(L"NTDLL.DLL");
win32::DWORD wlen = win32::FormatMessageW(0x00000800 /*FORMAT_MESSAGE_FROM_HMODULE*/ | 0x00001000 /*FORMAT_MESSAGE_FROM_SYSTEM*/ | 0x00000200 /*FORMAT_MESSAGE_IGNORE_INSERTS*/, ntdll, c, (1 << 10) /*MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)*/, buffer, 32768, nullptr);
size_t allocation = wlen + (wlen >> 1);
win32::DWORD bytes;
if(wlen == 0)
{
return _base::string_ref("failed to get message from system");
}
for(;;)
{
auto *p = static_cast<char *>(malloc(allocation)); // NOLINT
if(p == nullptr)
{
return _base::string_ref("failed to get message from system");
}
bytes = win32::WideCharToMultiByte(65001 /*CP_UTF8*/, 0, buffer, (int) (wlen + 1), p, (int) allocation, nullptr, nullptr);
if(bytes != 0)
{
char *end = strchr(p, 0);
while(end[-1] == 10 || end[-1] == 13)
{
--end;
}
*end = 0; // NOLINT
return _base::atomic_refcounted_string_ref(p, end - p);
}
free(p); // NOLINT
if(win32::GetLastError() == 0x7a /*ERROR_INSUFFICIENT_BUFFER*/)
{
allocation += allocation >> 2;
continue;
}
return _base::string_ref("failed to get message from system");
}
}
public:
//! The value type of the NT code, which is a `win32::NTSTATUS`
using value_type = win32::NTSTATUS;
using _base::string_ref;
public:
//! Default constructor
constexpr explicit _nt_code_domain(typename _base::unique_id_type id = 0x93f3b4487e4af25b) noexcept
: _base(id)
{
}
_nt_code_domain(const _nt_code_domain &) = default;
_nt_code_domain(_nt_code_domain &&) = default;
_nt_code_domain &operator=(const _nt_code_domain &) = default;
_nt_code_domain &operator=(_nt_code_domain &&) = default;
~_nt_code_domain() = default;
//! Constexpr singleton getter. Returns the constexpr nt_code_domain variable.
static inline constexpr const _nt_code_domain &get();
virtual string_ref name() const noexcept override { return string_ref("NT domain"); } // NOLINT
protected:
virtual bool _do_failure(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
return static_cast<const nt_code &>(code).value() < 0; // NOLINT
}
virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override // NOLINT
{
assert(code1.domain() == *this);
const auto &c1 = static_cast<const nt_code &>(code1); // NOLINT
if(code2.domain() == *this)
{
const auto &c2 = static_cast<const nt_code &>(code2); // NOLINT
return c1.value() == c2.value();
}
if(code2.domain() == generic_code_domain)
{
const auto &c2 = static_cast<const generic_code &>(code2); // NOLINT
if(static_cast<int>(c2.value()) == _nt_code_to_errno(c1.value()))
{
return true;
}
}
if(code2.domain() == win32_code_domain)
{
const auto &c2 = static_cast<const win32_code &>(code2); // NOLINT
if(c2.value() == _nt_code_to_win32_code(c1.value()))
{
return true;
}
}
return false;
}
virtual generic_code _generic_code(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const nt_code &>(code); // NOLINT
return generic_code(static_cast<errc>(_nt_code_to_errno(c.value())));
}
virtual string_ref _do_message(const status_code<void> &code) const noexcept override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const nt_code &>(code); // NOLINT
return _make_string_ref(c.value());
}
#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || 0L
SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override // NOLINT
{
assert(code.domain() == *this);
const auto &c = static_cast<const nt_code &>(code); // NOLINT
throw status_error<_nt_code_domain>(c);
}
#endif
};
//! (Windows only) A constexpr source variable for the NT code domain, which is that of NT kernel functions. Returned by `_nt_code_domain::get()`.
constexpr _nt_code_domain nt_code_domain;
inline constexpr const _nt_code_domain &_nt_code_domain::get()
{
return nt_code_domain;
}
SYSTEM_ERROR2_NAMESPACE_END
#endif
// NOT "com_code.hpp"
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! An erased-mutable status code suitably large for all the system codes
which can be returned on this system.
For Windows, these might be:
- `com_code` (`HRESULT`) [you need to include "com_code.hpp" explicitly for this]
- `nt_code` (`LONG`)
- `win32_code` (`DWORD`)
For POSIX, `posix_code` is possible.
You are guaranteed that `system_code` can be transported by the compiler
in exactly two CPU registers.
*/
using system_code = status_code<erased<intptr_t>>;
#ifndef NDEBUG
static_assert(sizeof(system_code) == 2 * sizeof(void *), "system_code is not exactly two pointers in size!");
static_assert(traits::is_move_bitcopying<system_code>::value, "system_code is not move bitcopying!");
#endif
SYSTEM_ERROR2_NAMESPACE_END
#endif
SYSTEM_ERROR2_NAMESPACE_BEGIN
/*! An erased `system_code` which is always a failure. The closest equivalent to
`std::error_code`, except it cannot be null and cannot be modified.
This refines `system_code` into an `error` object meeting the requirements of
[P0709 Zero-overhead deterministic exceptions](https://wg21.link/P0709).
Differences from `system_code`:
- Always a failure (this is checked at construction, and if not the case,
the program is terminated as this is a logic error)
- No default construction.
- No empty state possible.
- Is immutable.
As with `system_code`, it remains guaranteed to be two CPU registers in size,
and move bitcopying.
*/
using error = errored_status_code<erased<system_code::value_type>>;
#ifndef NDEBUG
static_assert(sizeof(error) == 2 * sizeof(void *), "error is not exactly two pointers in size!");
static_assert(traits::is_move_bitcopying<error>::value, "error is not move bitcopying!");
#endif
SYSTEM_ERROR2_NAMESPACE_END
#endif
#endif
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace trait
{
namespace detail
{
// Shortcut this for lower build impact. Used to tell outcome's converting constructors
// that they can do E => EC or E => EP as necessary.
template <class DomainType> struct _is_error_code_available<SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
{
static constexpr bool value = true;
using type = SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>;
};
template <class DomainType> struct _is_error_code_available<SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>
{
static constexpr bool value = true;
using type = SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>;
};
} // namespace detail
template <class DomainType> struct is_move_bitcopying<SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>
{
static constexpr bool value = SYSTEM_ERROR2_NAMESPACE::traits::is_move_bitcopying<SYSTEM_ERROR2_NAMESPACE::status_code<DomainType>>::value;
};
template <class DomainType> struct is_move_bitcopying<SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>
{
static constexpr bool value = SYSTEM_ERROR2_NAMESPACE::traits::is_move_bitcopying<SYSTEM_ERROR2_NAMESPACE::errored_status_code<DomainType>>::value;
};
} // namespace trait
namespace detail
{
// Customise _set_error_is_errno
template <class State> constexpr inline void _set_error_is_errno(State &state, const SYSTEM_ERROR2_NAMESPACE::generic_code & /*unused*/)
{
state._status.set_have_error_is_errno(true);
}
#ifndef SYSTEM_ERROR2_NOT_POSIX
template <class State> constexpr inline void _set_error_is_errno(State &state, const SYSTEM_ERROR2_NAMESPACE::posix_code & /*unused*/)
{
state._status.set_have_error_is_errno(true);
}
#endif
template <class State> constexpr inline void _set_error_is_errno(State &state, const SYSTEM_ERROR2_NAMESPACE::errc & /*unused*/)
{
state._status.set_have_error_is_errno(true);
}
} // namespace detail
namespace experimental
{
using namespace SYSTEM_ERROR2_NAMESPACE;
using OUTCOME_V2_NAMESPACE::failure;
using OUTCOME_V2_NAMESPACE::success;
namespace policy
{
using namespace OUTCOME_V2_NAMESPACE::policy;
template <class T, class EC, class E> struct status_code_throw
{
static_assert(!std::is_same<T, T>::value,
"policy::status_code_throw not specialised for these types, did you use status_result<T, status_code<DomainType>, E>?");
};
template <class T, class DomainType> struct status_code_throw<T, status_code<DomainType>, void> : base
{
using _base = base;
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
if(base::_has_error(static_cast<Impl &&>(self)))
{
#ifdef __cpp_exceptions
base::_error(static_cast<Impl &&>(self)).throw_exception();
#else
OUTCOME_THROW_EXCEPTION("wide value check failed");
#endif
}
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self) { _base::narrow_error_check(static_cast<Impl &&>(self)); }
};
template <class T, class DomainType>
struct status_code_throw<T, errored_status_code<DomainType>, void> : status_code_throw<T, status_code<DomainType>, void>
{
status_code_throw() = default;
using status_code_throw<T, status_code<DomainType>, void>::status_code_throw;
};
template <class T, class EC>
using default_status_result_policy = std::conditional_t< //
std::is_void<EC>::value, //
OUTCOME_V2_NAMESPACE::policy::terminate, //
std::conditional_t<is_status_code<EC>::value || is_errored_status_code<EC>::value, //
status_code_throw<T, EC, void>, //
OUTCOME_V2_NAMESPACE::policy::fail_to_compile_observers //
>>;
} // namespace policy
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S = errored_status_code<erased<typename system_code::value_type>>,
class NoValuePolicy = policy::default_status_result_policy<R, S>> //
using status_result = basic_result<R, S, NoValuePolicy>;
} // namespace experimental
OUTCOME_V2_NAMESPACE_END
#endif
// Boost.Outcome #include "boost/exception_ptr.hpp"
SYSTEM_ERROR2_NAMESPACE_BEGIN
template <class DomainType> inline std::exception_ptr basic_outcome_failure_exception_from_error(const status_code<DomainType> &sc)
{
(void) sc;
#ifdef __cpp_exceptions
try
{
sc.throw_exception();
}
catch(...)
{
return std::current_exception();
}
#endif
return {};
}
SYSTEM_ERROR2_NAMESPACE_END
OUTCOME_V2_NAMESPACE_EXPORT_BEGIN
namespace experimental
{
namespace policy
{
template <class T, class EC, class E>
using default_status_outcome_policy = std::conditional_t< //
std::is_void<EC>::value && std::is_void<E>::value, //
OUTCOME_V2_NAMESPACE::policy::terminate, //
std::conditional_t<(is_status_code<EC>::value || is_errored_status_code<EC>::value) &&
(std::is_void<E>::value || OUTCOME_V2_NAMESPACE::trait::is_exception_ptr_available<E>::value), //
status_code_throw<T, EC, E>, //
OUTCOME_V2_NAMESPACE::policy::fail_to_compile_observers //
>>;
} // namespace policy
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
template <class R, class S = errored_status_code<erased<typename system_code::value_type>>, class P = std::exception_ptr,
class NoValuePolicy = policy::default_status_outcome_policy<R, S, P>> //
using status_outcome = basic_outcome<R, S, P, NoValuePolicy>;
namespace policy
{
template <class T, class DomainType, class E> struct status_code_throw<T, status_code<DomainType>, E> : base
{
using _base = base;
template <class Impl> static constexpr void wide_value_check(Impl &&self)
{
if(!base::_has_value(static_cast<Impl &&>(self)))
{
if(base::_has_exception(static_cast<Impl &&>(self)))
{
OUTCOME_V2_NAMESPACE::policy::detail::_rethrow_exception<trait::is_exception_ptr_available<E>::value>(
base::_exception<T, status_code<DomainType>, E, status_code_throw>(static_cast<Impl &&>(self))); // NOLINT
}
if(base::_has_error(static_cast<Impl &&>(self)))
{
#ifdef __cpp_exceptions
base::_error(static_cast<Impl &&>(self)).throw_exception();
#else
OUTCOME_THROW_EXCEPTION("wide value check failed");
#endif
}
}
}
template <class Impl> static constexpr void wide_error_check(Impl &&self) { _base::narrow_error_check(static_cast<Impl &&>(self)); }
template <class Impl> static constexpr void wide_exception_check(Impl &&self) { _base::narrow_exception_check(static_cast<Impl &&>(self)); }
};
template <class T, class DomainType, class E>
struct status_code_throw<T, errored_status_code<DomainType>, E> : status_code_throw<T, status_code<DomainType>, E>
{
status_code_throw() = default;
using status_code_throw<T, status_code<DomainType>, E>::status_code_throw;
};
} // namespace policy
} // namespace experimental
OUTCOME_V2_NAMESPACE_END
#endif
/* Try operation macros
(C) 2017-2021 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: July 2017
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the accompanying file
Licence.txt or at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file Licence.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef OUTCOME_TRY_HPP
#define OUTCOME_TRY_HPP
OUTCOME_V2_NAMESPACE_BEGIN
namespace detail
{
struct has_value_overload
{
};
struct as_failure_overload
{
};
struct assume_error_overload
{
};
struct error_overload
{
};
struct assume_value_overload
{
};
struct value_overload
{
};
//#ifdef __APPLE__
// OUTCOME_TEMPLATE(class T, class R = decltype(std::declval<T>()._xcode_workaround_as_failure()))
//#else
OUTCOME_TEMPLATE(class T, class R = decltype(std::declval<T>().as_failure()))
//#endif
OUTCOME_TREQUIRES(OUTCOME_TPRED(OUTCOME_V2_NAMESPACE::is_failure_type<R>))
constexpr inline bool has_as_failure(int /*unused */) { return true; }
template <class T> constexpr inline bool has_as_failure(...) { return false; }
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<T>().assume_error()))
constexpr inline bool has_assume_error(int /*unused */) { return true; }
template <class T> constexpr inline bool has_assume_error(...) { return false; }
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<T>().error()))
constexpr inline bool has_error(int /*unused */) { return true; }
template <class T> constexpr inline bool has_error(...) { return false; }
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<T>().assume_value()))
constexpr inline bool has_assume_value(int /*unused */) { return true; }
template <class T> constexpr inline bool has_assume_value(...) { return false; }
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<T>().value()))
constexpr inline bool has_value(int /*unused */) { return true; }
template <class T> constexpr inline bool has_value(...) { return false; }
} // namespace detail
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TEXPR(std::declval<T>().has_value()))
constexpr inline bool try_operation_has_value(T &&v, detail::has_value_overload = {})
{
return v.has_value();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::has_as_failure<T>(5)))
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::as_failure_overload = {})
{
return static_cast<T &&>(v).as_failure();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!detail::has_as_failure<T>(5) && detail::has_assume_error<T>(5)))
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::assume_error_overload = {})
{
return failure(static_cast<T &&>(v).assume_error());
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!detail::has_as_failure<T>(5) && !detail::has_assume_error<T>(5) && detail::has_error<T>(5)))
constexpr inline decltype(auto) try_operation_return_as(T &&v, detail::error_overload = {})
{
return failure(static_cast<T &&>(v).error());
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(detail::has_assume_value<T>(5)))
constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::assume_value_overload = {})
{
return static_cast<T &&>(v).assume_value();
}
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
OUTCOME_TEMPLATE(class T)
OUTCOME_TREQUIRES(OUTCOME_TPRED(!detail::has_assume_value<T>(5) && detail::has_value<T>(5)))
constexpr inline decltype(auto) try_operation_extract_value(T &&v, detail::value_overload = {})
{
return static_cast<T &&>(v).value();
}
OUTCOME_V2_NAMESPACE_END
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wparentheses"
#endif
#define OUTCOME_TRY_GLUE2(x, y) x##y
#define OUTCOME_TRY_GLUE(x, y) OUTCOME_TRY_GLUE2(x, y)
#define OUTCOME_TRY_UNIQUE_NAME OUTCOME_TRY_GLUE(_outcome_try_unique_name_temporary, __COUNTER__)
#define OUTCOME_TRY_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
#define OUTCOME_TRY_EXPAND_ARGS(args) OUTCOME_TRY_RETURN_ARG_COUNT args
#define OUTCOME_TRY_COUNT_ARGS_MAX8(...) OUTCOME_TRY_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define OUTCOME_TRY_OVERLOAD_MACRO2(name, count) name##count
#define OUTCOME_TRY_OVERLOAD_MACRO1(name, count) OUTCOME_TRY_OVERLOAD_MACRO2(name, count)
#define OUTCOME_TRY_OVERLOAD_MACRO(name, count) OUTCOME_TRY_OVERLOAD_MACRO1(name, count)
#define OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
#define OUTCOME_TRY_CALL_OVERLOAD(name, ...) OUTCOME_TRY_OVERLOAD_GLUE(OUTCOME_TRY_OVERLOAD_MACRO(name, OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
#define _OUTCOME_TRY_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
#define _OUTCOME_TRY_EXPAND_ARGS(args) _OUTCOME_TRY_RETURN_ARG_COUNT args
#define _OUTCOME_TRY_COUNT_ARGS_MAX8(...) _OUTCOME_TRY_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define _OUTCOME_TRY_OVERLOAD_MACRO2(name, count) name##count
#define _OUTCOME_TRY_OVERLOAD_MACRO1(name, count) _OUTCOME_TRY_OVERLOAD_MACRO2(name, count)
#define _OUTCOME_TRY_OVERLOAD_MACRO(name, count) _OUTCOME_TRY_OVERLOAD_MACRO1(name, count)
#define _OUTCOME_TRY_OVERLOAD_GLUE(x, y) x y
#define _OUTCOME_TRY_CALL_OVERLOAD(name, ...) _OUTCOME_TRY_OVERLOAD_GLUE(_OUTCOME_TRY_OVERLOAD_MACRO(name, _OUTCOME_TRY_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
#ifndef OUTCOME_TRY_LIKELY_IF
#if (__cplusplus >= 202000L || _HAS_CXX20) && (!defined(__clang__) || __clang_major__ >= 12)
#define OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__) [[likely]]
#elif defined(__clang__) || defined(__GNUC__)
#define OUTCOME_TRY_LIKELY_IF(...) if(__builtin_expect(!!(__VA_ARGS__), true))
#else
#define OUTCOME_TRY_LIKELY_IF(...) if(__VA_ARGS__)
#endif
#endif
#define OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK(...) __VA_ARGS__
#define OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE3(unique, ...) auto unique = (__VA_ARGS__)
#define OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE2(x) x
#define OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE(unique, x, ...) OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE2(OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE3(unique, __VA_ARGS__))
#define OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED3(unique, x, y, ...) x unique = (__VA_ARGS__)
#define OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED2(x) x
#define OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED(unique, ...) OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED2(OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED3(unique, __VA_ARGS__))
#define OUTCOME_TRYV2_UNIQUE_STORAGE1(...) OUTCOME_TRYV2_UNIQUE_STORAGE_DEDUCE
#define OUTCOME_TRYV2_UNIQUE_STORAGE2(...) OUTCOME_TRYV2_UNIQUE_STORAGE_SPECIFIED
#define OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, ...) _OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_TRYV2_UNIQUE_STORAGE, OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec) (unique, OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec, __VA_ARGS__)
// Use if(!expr); else as some compilers assume else clauses are always unlikely
#define OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, spec, ...) OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, __VA_ARGS__); OUTCOME_TRY_LIKELY_IF(::OUTCOME_V2_NAMESPACE::try_operation_has_value(unique)); else retstmt ::OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))
#define OUTCOME_TRYV3_FAILURE_LIKELY(unique, retstmt, spec, ...) OUTCOME_TRYV2_UNIQUE_STORAGE(unique, spec, __VA_ARGS__); OUTCOME_TRY_LIKELY_IF(!OUTCOME_V2_NAMESPACE::try_operation_has_value(unique)) retstmt ::OUTCOME_V2_NAMESPACE::try_operation_return_as(static_cast<decltype(unique) &&>(unique))
#define OUTCOME_TRY2_VAR_SECOND2(x, var) var
#define OUTCOME_TRY2_VAR_SECOND3(x, y, ...) x y
#define OUTCOME_TRY2_VAR(spec) _OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_TRY2_VAR_SECOND, OUTCOME_TRYV2_UNIQUE_STORAGE_UNPACK spec, spec)
#define OUTCOME_TRY2_SUCCESS_LIKELY(unique, retstmt, var, ...) OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, var, __VA_ARGS__); OUTCOME_TRY2_VAR(var) = ::OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique))
#define OUTCOME_TRY2_FAILURE_LIKELY(unique, retstmt, var, ...) OUTCOME_TRYV3_FAILURE_LIKELY(unique, retstmt, var, __VA_ARGS__); OUTCOME_TRY2_VAR(var) = ::OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique))
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYV(...) OUTCOME_TRYV2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, deduce, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYV_FAILURE_LIKELY(...) OUTCOME_TRYV3_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, deduce, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYV(...) OUTCOME_TRYV2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYV_FAILURE_LIKELY(...) OUTCOME_TRYV3_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYV2(s, ...) OUTCOME_TRYV2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, (s,), __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYV2_FAILURE_LIKELY(s, ...) OUTCOME_TRYV3_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, (s,), __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYV2(s, ...) OUTCOME_TRYV2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, (s,), __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYV2_FAILURE_LIKELY(s, ...) OUTCOME_TRYV3_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, s(,), __VA_ARGS__)
#if defined(__GNUC__) || defined(__clang__)
#define OUTCOME_TRYX2(unique, retstmt, ...) ({ OUTCOME_TRYV2_SUCCESS_LIKELY(unique, retstmt, deduce, __VA_ARGS__); ::OUTCOME_V2_NAMESPACE::try_operation_extract_value(static_cast<decltype(unique) &&>(unique)); })
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYX(...) OUTCOME_TRYX2(OUTCOME_TRY_UNIQUE_NAME, return, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYX(...) OUTCOME_TRYX2(OUTCOME_TRY_UNIQUE_NAME, co_return, __VA_ARGS__)
#endif
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYA(v, ...) OUTCOME_TRY2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRYA_FAILURE_LIKELY(v, ...) OUTCOME_TRY2_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYA(v, ...) OUTCOME_TRY2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRYA_FAILURE_LIKELY(v, ...) OUTCOME_TRY2_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, v, __VA_ARGS__)
#define OUTCOME_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME_TRYA(a, b, c, d, e, f, g, h)
#define OUTCOME_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME_TRYA(a, b, c, d, e, f, g)
#define OUTCOME_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME_TRYA(a, b, c, d, e, f)
#define OUTCOME_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME_TRYA(a, b, c, d, e)
#define OUTCOME_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME_TRYA(a, b, c, d)
#define OUTCOME_TRY_INVOKE_TRY3(a, b, c) OUTCOME_TRYA(a, b, c)
#define OUTCOME_TRY_INVOKE_TRY2(a, b) OUTCOME_TRYA(a, b)
#define OUTCOME_TRY_INVOKE_TRY1(a) OUTCOME_TRYV(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d, e)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c, d)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME_TRYA_FAILURE_LIKELY(a, b, c)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME_TRYA_FAILURE_LIKELY(a, b)
#define OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) OUTCOME_TRYV_FAILURE_LIKELY(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRY_FAILURE_LIKELY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME_CO_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME_CO_TRYA(a, b, c, d, e, f, g, h)
#define OUTCOME_CO_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME_CO_TRYA(a, b, c, d, e, f, g)
#define OUTCOME_CO_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME_CO_TRYA(a, b, c, d, e, f)
#define OUTCOME_CO_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME_CO_TRYA(a, b, c, d, e)
#define OUTCOME_CO_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME_CO_TRYA(a, b, c, d)
#define OUTCOME_CO_TRY_INVOKE_TRY3(a, b, c) OUTCOME_CO_TRYA(a, b, c)
#define OUTCOME_CO_TRY_INVOKE_TRY2(a, b) OUTCOME_CO_TRYA(a, b)
#define OUTCOME_CO_TRY_INVOKE_TRY1(a) OUTCOME_CO_TRYV(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_CO_TRY_INVOKE_TRY, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_TRY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_TRY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c, d)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b, c)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME_CO_TRYA_FAILURE_LIKELY(a, b)
#define OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) OUTCOME_CO_TRYV_FAILURE_LIKELY(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME_CO_TRY_FAILURE_LIKELY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME_CO_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_TRYA(v, ...) OUTCOME_TRY2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, deduce, auto &&v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_TRYA_FAILURE_LIKELY(v, ...) OUTCOME_TRY2_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, return, deduce, auto &&v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_CO_TRYA(v, ...) OUTCOME_TRY2_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_return, deduce, auto &&v, __VA_ARGS__)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_CO_TRYA_FAILURE_LIKELY(v, ...) OUTCOME_TRY2_FAILURE_LIKELY(OUTCOME_TRY_UNIQUE_NAME, co_retrn, deduce, auto &&v, __VA_ARGS__)
#define OUTCOME21_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_TRYA(a, b, c, d, e, f, g, h)
#define OUTCOME21_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_TRYA(a, b, c, d, e, f, g)
#define OUTCOME21_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_TRYA(a, b, c, d, e, f)
#define OUTCOME21_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_TRYA(a, b, c, d, e)
#define OUTCOME21_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME21_TRYA(a, b, c, d)
#define OUTCOME21_TRY_INVOKE_TRY3(a, b, c) OUTCOME21_TRYA(a, b, c)
#define OUTCOME21_TRY_INVOKE_TRY2(a, b) OUTCOME21_TRYA(a, b)
#define OUTCOME21_TRY_INVOKE_TRY1(a) OUTCOME_TRYV(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_TRY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_TRY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d, e)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c, d)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME21_TRYA_FAILURE_LIKELY(a, b, c)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME21_TRYA_FAILURE_LIKELY(a, b)
#define OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) OUTCOME_TRYV_FAILURE_LIKELY(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_TRY_FAILURE_LIKELY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME21_CO_TRY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_CO_TRYA(a, b, c, d, e, f, g, h)
#define OUTCOME21_CO_TRY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_CO_TRYA(a, b, c, d, e, f, g)
#define OUTCOME21_CO_TRY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_CO_TRYA(a, b, c, d, e, f)
#define OUTCOME21_CO_TRY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_CO_TRYA(a, b, c, d, e)
#define OUTCOME21_CO_TRY_INVOKE_TRY4(a, b, c, d) OUTCOME21_CO_TRYA(a, b, c, d)
#define OUTCOME21_CO_TRY_INVOKE_TRY3(a, b, c) OUTCOME21_CO_TRYA(a, b, c)
#define OUTCOME21_CO_TRY_INVOKE_TRY2(a, b) OUTCOME21_CO_TRYA(a, b)
#define OUTCOME21_CO_TRY_INVOKE_TRY1(a) OUTCOME_CO_TRYV(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_CO_TRY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_CO_TRY_INVOKE_TRY, __VA_ARGS__)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY8(a, b, c, d, e, f, g, h) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g, h)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY7(a, b, c, d, e, f, g) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f, g)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY6(a, b, c, d, e, f) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e, f)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY5(a, b, c, d, e) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d, e)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY4(a, b, c, d) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c, d)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY3(a, b, c) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b, c)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY2(a, b) OUTCOME21_CO_TRYA_FAILURE_LIKELY(a, b)
#define OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY1(a) OUTCOME_CO_TRYV_FAILURE_LIKELY(a)
/*! AWAITING HUGO JSON CONVERSION TOOL
SIGNATURE NOT RECOGNISED
*/
#define OUTCOME21_CO_TRY_FAILURE_LIKELY(...) OUTCOME_TRY_CALL_OVERLOAD(OUTCOME21_CO_TRY_FAILURE_LIKELY_INVOKE_TRY, __VA_ARGS__)
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif