Warning, file /include/boost/outcome/experimental/status-code/nested_status_code.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NESTED_STATUS_CODE_HPP
0026 #define BOOST_OUTCOME_SYSTEM_ERROR2_NESTED_STATUS_CODE_HPP
0027
0028 #include "quick_status_code_from_enum.hpp"
0029
0030 #include <memory> // for allocator
0031
0032 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
0033
0034 namespace detail
0035 {
0036 template <class StatusCode, class Allocator> class indirecting_domain : public status_code_domain
0037 {
0038 template <class DomainType> friend class status_code;
0039 using _base = status_code_domain;
0040
0041 public:
0042 struct payload_type
0043 {
0044 using allocator_traits = std::allocator_traits<Allocator>;
0045 union
0046 {
0047 char _uninit[sizeof(StatusCode)];
0048 StatusCode sc;
0049 };
0050 Allocator alloc;
0051
0052 payload_type(StatusCode _sc, Allocator _alloc)
0053 : alloc(static_cast<Allocator &&>(_alloc))
0054 {
0055 allocator_traits::construct(alloc, &sc, static_cast<StatusCode &&>(_sc));
0056 }
0057 payload_type(const payload_type &) = delete;
0058 payload_type(payload_type &&) = delete;
0059 ~payload_type() { allocator_traits::destroy(alloc, &sc); }
0060 };
0061 using value_type = payload_type *;
0062 using payload_allocator_traits = typename payload_type::allocator_traits::template rebind_traits<payload_type>;
0063 using _base::string_ref;
0064
0065 constexpr indirecting_domain() noexcept
0066 : _base(0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id() )
0067 {
0068 }
0069 indirecting_domain(const indirecting_domain &) = default;
0070 indirecting_domain(indirecting_domain &&) = default;
0071 indirecting_domain &operator=(const indirecting_domain &) = default;
0072 indirecting_domain &operator=(indirecting_domain &&) = default;
0073 ~indirecting_domain() = default;
0074
0075 #if __cplusplus < 201402L && !defined(_MSC_VER)
0076 static inline const indirecting_domain &get()
0077 {
0078 static indirecting_domain v;
0079 return v;
0080 }
0081 #else
0082 static inline constexpr const indirecting_domain &get();
0083 #endif
0084
0085 virtual string_ref name() const noexcept override { return typename StatusCode::domain_type().name(); }
0086
0087 virtual payload_info_t payload_info() const noexcept override
0088 {
0089 return {sizeof(value_type), sizeof(status_code_domain *) + sizeof(value_type),
0090 (alignof(value_type) > alignof(status_code_domain *)) ? alignof(value_type) : alignof(status_code_domain *)};
0091 }
0092
0093 protected:
0094 using _mycode = status_code<indirecting_domain>;
0095 virtual bool _do_failure(const status_code<void> &code) const noexcept override
0096 {
0097 assert(code.domain() == *this);
0098 const auto &c = static_cast<const _mycode &>(code);
0099 return static_cast<status_code_domain &&>(typename StatusCode::domain_type())._do_failure(c.value()->sc);
0100 }
0101 virtual bool _do_equivalent(const status_code<void> &code1, const status_code<void> &code2) const noexcept override
0102 {
0103 assert(code1.domain() == *this);
0104 const auto &c1 = static_cast<const _mycode &>(code1);
0105 return static_cast<status_code_domain &&>(typename StatusCode::domain_type())._do_equivalent(c1.value()->sc, code2);
0106 }
0107 virtual generic_code _generic_code(const status_code<void> &code) const noexcept override
0108 {
0109 assert(code.domain() == *this);
0110 const auto &c = static_cast<const _mycode &>(code);
0111 return static_cast<status_code_domain &&>(typename StatusCode::domain_type())._generic_code(c.value()->sc);
0112 }
0113 virtual string_ref _do_message(const status_code<void> &code) const noexcept override
0114 {
0115 assert(code.domain() == *this);
0116 const auto &c = static_cast<const _mycode &>(code);
0117 return static_cast<status_code_domain &&>(typename StatusCode::domain_type())._do_message(c.value()->sc);
0118 }
0119 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0120 BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN virtual void _do_throw_exception(const status_code<void> &code) const override
0121 {
0122 assert(code.domain() == *this);
0123 const auto &c = static_cast<const _mycode &>(code);
0124 static_cast<status_code_domain &&>(typename StatusCode::domain_type())._do_throw_exception(c.value()->sc);
0125 abort();
0126 }
0127 #endif
0128 virtual bool _do_erased_copy(status_code<void> &dst, const status_code<void> &src, payload_info_t dstinfo) const override
0129 {
0130
0131 const auto srcinfo = payload_info();
0132 assert(src.domain() == *this);
0133 if(dstinfo.total_size < srcinfo.total_size)
0134 {
0135 return false;
0136 }
0137 auto &d = static_cast<_mycode &>(dst);
0138 const auto &_s = static_cast<const _mycode &>(src);
0139 const payload_type &sp = *_s.value();
0140 typename payload_allocator_traits::template rebind_alloc<payload_type> payload_alloc(sp.alloc);
0141 auto *dp = payload_allocator_traits::allocate(payload_alloc, 1);
0142 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0143 try
0144 #endif
0145 {
0146 payload_allocator_traits::construct(payload_alloc, dp, sp.sc, sp.alloc);
0147 new(BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(d)) _mycode(in_place, dp);
0148 }
0149 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0150 catch(...)
0151 {
0152 payload_allocator_traits::deallocate(payload_alloc, dp, 1);
0153 throw;
0154 }
0155 #endif
0156 return true;
0157 }
0158 virtual void _do_erased_destroy(status_code<void> &code, payload_info_t ) const noexcept override
0159 {
0160 assert(code.domain() == *this);
0161 auto &c = static_cast<_mycode &>(code);
0162 payload_type *p = c.value();
0163 typename payload_allocator_traits::template rebind_alloc<payload_type> payload_alloc(p->alloc);
0164 payload_allocator_traits::destroy(payload_alloc, p);
0165 payload_allocator_traits::deallocate(payload_alloc, p, 1);
0166 }
0167 };
0168 #if __cplusplus >= 201402L || defined(_MSC_VER)
0169 template <class StatusCode, class Allocator> constexpr indirecting_domain<StatusCode, Allocator> _indirecting_domain{};
0170 template <class StatusCode, class Allocator>
0171 inline constexpr const indirecting_domain<StatusCode, Allocator> &indirecting_domain<StatusCode, Allocator>::get()
0172 {
0173 return _indirecting_domain<StatusCode, Allocator>;
0174 }
0175 #endif
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class T, class Alloc = std::allocator<typename std::decay<T>::type>)
0186 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<T>::value))
0187 inline status_code<detail::erased<typename std::add_pointer<typename std::decay<T>::type>::type>> make_nested_status_code(T &&v, Alloc alloc = {})
0188 {
0189 using status_code_type = typename std::decay<T>::type;
0190 using domain_type = detail::indirecting_domain<status_code_type, typename std::decay<Alloc>::type>;
0191 using payload_allocator_traits = typename domain_type::payload_allocator_traits;
0192 typename payload_allocator_traits::template rebind_alloc<typename domain_type::payload_type> payload_alloc(alloc);
0193 auto *p = payload_allocator_traits::allocate(payload_alloc, 1);
0194 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0195 try
0196 #endif
0197 {
0198 payload_allocator_traits::construct(payload_alloc, p, static_cast<T &&>(v), static_cast<Alloc &&>(alloc));
0199 return status_code<domain_type>(in_place, p);
0200 }
0201 #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) || defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE)
0202 catch(...)
0203 {
0204 payload_allocator_traits::deallocate(payload_alloc, p, 1);
0205 throw;
0206 }
0207 #endif
0208 }
0209
0210
0211
0212
0213 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class StatusCode, class U)
0214 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<StatusCode>::value)) inline StatusCode *get_if(status_code<detail::erased<U>> *v) noexcept
0215 {
0216 if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
0217 {
0218 return nullptr;
0219 }
0220 union
0221 {
0222 U value;
0223 StatusCode *ret;
0224 };
0225 value = v->value();
0226 return ret;
0227 }
0228
0229 BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class StatusCode, class U)
0230 BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_status_code<StatusCode>::value))
0231 inline const StatusCode *get_if(const status_code<detail::erased<U>> *v) noexcept
0232 {
0233 if((0xc44f7bdeb2cc50e9 ^ typename StatusCode::domain_type().id()) != v->domain().id())
0234 {
0235 return nullptr;
0236 }
0237 union
0238 {
0239 U value;
0240 const StatusCode *ret;
0241 };
0242 value = v->value();
0243 return ret;
0244 }
0245
0246
0247
0248
0249 template <class U> inline typename status_code_domain::unique_id_type get_id(const status_code<detail::erased<U>> &v) noexcept
0250 {
0251 return 0xc44f7bdeb2cc50e9 ^ v.domain().id();
0252 }
0253
0254 BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
0255
0256 #endif