add boost on mac
This commit is contained in:
@@ -0,0 +1,502 @@
|
||||
/* Proposed SG14 status_code
|
||||
(C) 2018-2019 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
|
||||
File Created: Feb 2018
|
||||
|
||||
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
#define BOOST_OUTCOME_SYSTEM_ERROR2_STATUS_CODE_HPP
|
||||
|
||||
#include "status_code_domain.hpp"
|
||||
|
||||
#if __cplusplus >= 201700 || _HAS_CXX17
|
||||
// 0.26
|
||||
#include <utility> // for in_place
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
|
||||
using in_place_t = std::in_place_t;
|
||||
using std::in_place;
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#else
|
||||
|
||||
BOOST_OUTCOME_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{};
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
BOOST_OUTCOME_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_relocating<ErasedType>::value`.
|
||||
*/
|
||||
template <class ErasedType, //
|
||||
typename std::enable_if<traits::is_move_relocating<ErasedType>::value, bool>::type = true>
|
||||
struct erased
|
||||
{
|
||||
using value_type = ErasedType;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// 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...>;
|
||||
} // 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 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) {}
|
||||
|
||||
public:
|
||||
//! Return the status code domain.
|
||||
constexpr const status_code_domain &domain() const noexcept { return *_domain; }
|
||||
//! True if the status code is empty.
|
||||
BOOST_OUTCOME_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 { return (_domain != nullptr) ? _domain->_do_message(*this) : 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) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
|
||||
//! Throw a code as a C++ exception.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN void throw_exception() const { _domain->_do_throw_exception(*this); }
|
||||
#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 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.
|
||||
BOOST_OUTCOME_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 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 this->_value; }
|
||||
|
||||
protected:
|
||||
status_code_storage() = default;
|
||||
status_code_storage(const status_code_storage &) = default;
|
||||
BOOST_OUTCOME_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;
|
||||
BOOST_OUTCOME_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 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;
|
||||
|
||||
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.
|
||||
BOOST_OUTCOME_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)...))
|
||||
{
|
||||
}
|
||||
//! Explicit in-place construction.
|
||||
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.
|
||||
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`.
|
||||
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`.
|
||||
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 relocating, 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
|
||||
}
|
||||
|
||||
//! Assignment from a `value_type`.
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code &operator=(const value_type &v) noexcept(std::is_nothrow_copy_assignable<value_type>::value)
|
||||
{
|
||||
this->_value = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Return a reference to a string textually representing a code.
|
||||
string_ref message() const noexcept { return this->_domain ? string_ref(this->domain()._do_message(*this)) : string_ref("(empty)"); }
|
||||
};
|
||||
|
||||
namespace traits
|
||||
{
|
||||
template <class DomainType> struct is_move_relocating<status_code<DomainType>>
|
||||
{
|
||||
static constexpr bool value = is_move_relocating<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 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<!detail::is_erased_status_code<status_code<DomainType>>::value //
|
||||
&& 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(), detail::erasure_cast<value_type>(v.value()))
|
||||
{
|
||||
}
|
||||
//! Implicit move construction from any other status code if its value type is trivially copyable or move relocating 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>
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 status_code(status_code<DomainType> &&v) noexcept // NOLINT
|
||||
: _base(typename _base::_value_type_constructor{}, &v.domain(), 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)...))
|
||||
{
|
||||
}
|
||||
|
||||
/**** By rights ought to be removed in any formal standard ****/
|
||||
//! Reset the code to empty.
|
||||
BOOST_OUTCOME_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_relocating<status_code<erased<ErasedType>>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
} // namespace traits
|
||||
|
||||
BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user