config.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /* Proposed SG14 status_code
  2. (C) 2018 - 2021 Niall Douglas <http://www.nedproductions.biz/> (5 commits)
  3. File Created: Feb 2018
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License in the accompanying file
  7. Licence.txt or at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. Distributed under the Boost Software License, Version 1.0.
  15. (See accompanying file Licence.txt or copy at
  16. http://www.boost.org/LICENSE_1_0.txt)
  17. */
  18. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONFIG_HPP
  19. #define BOOST_OUTCOME_SYSTEM_ERROR2_CONFIG_HPP
  20. // < 0.1 each
  21. #include <cassert>
  22. #include <cstddef> // for size_t
  23. #include <cstdlib> // for free
  24. // 0.22
  25. #include <type_traits>
  26. // 0.29
  27. #include <atomic>
  28. // 0.28 (0.15 of which is exception_ptr)
  29. #include <exception> // for std::exception
  30. // <new> includes <exception>, <exception> includes <new>
  31. #include <new>
  32. // 0.01
  33. #include <initializer_list>
  34. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
  35. #ifdef __has_include
  36. #if __has_include(<bit>) && (__cplusplus >= 202002L || _HAS_CXX20)
  37. #define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 1
  38. #endif
  39. #elif __cplusplus >= 202002L
  40. #define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 1
  41. #endif
  42. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
  43. #define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 0
  44. #endif
  45. #endif
  46. #if BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
  47. #include <bit>
  48. #if __cpp_lib_bit_cast < 201806L
  49. #undef BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
  50. #define BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST 0
  51. #endif
  52. #endif
  53. #if BOOST_OUTCOME_SYSTEM_ERROR2_USE_STD_ADDRESSOF
  54. #include <memory> // for std::addressof
  55. #define BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(...) std::addressof(__VA_ARGS__)
  56. #else
  57. #define BOOST_OUTCOME_SYSTEM_ERROR2_ADDRESS_OF(...) (&__VA_ARGS__)
  58. #endif
  59. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
  60. #if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
  61. //! Defined to be `constexpr` when on C++ 14 or better compilers. Usually automatic, can be overriden.
  62. #define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14 constexpr
  63. #else
  64. #define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR14
  65. #endif
  66. #endif
  67. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20
  68. #if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || __cplusplus >= 202000 || _HAS_CXX20
  69. //! Defined to be `constexpr` when on C++ 20 or better compilers. Usually automatic, can be overriden.
  70. #define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20 constexpr
  71. #else
  72. #define BOOST_OUTCOME_SYSTEM_ERROR2_CONSTEXPR20
  73. #endif
  74. #endif
  75. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
  76. #if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
  77. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
  78. #endif
  79. #endif
  80. #if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
  81. #ifdef __has_cpp_attribute
  82. #if __has_cpp_attribute(noreturn)
  83. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN [[noreturn]]
  84. #endif
  85. #endif
  86. #endif
  87. #if !defined(BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN)
  88. #if defined(_MSC_VER)
  89. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __declspec(noreturn)
  90. #elif defined(__GNUC__)
  91. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN __attribute__((__noreturn__))
  92. #else
  93. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
  94. #endif
  95. #endif
  96. // GCCs before 7 don't grok [[noreturn]] virtual functions, and warn annoyingly
  97. #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 7
  98. #undef BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
  99. #define BOOST_OUTCOME_SYSTEM_ERROR2_NORETURN
  100. #endif
  101. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
  102. #if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (_HAS_CXX17 && _MSC_VER >= 1911 /* VS2017.3 */)
  103. #define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
  104. #endif
  105. #endif
  106. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
  107. #ifdef __has_cpp_attribute
  108. #if __has_cpp_attribute(nodiscard)
  109. #define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD [[nodiscard]]
  110. #endif
  111. #elif defined(__clang__)
  112. #define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD __attribute__((warn_unused_result))
  113. #elif defined(_MSC_VER)
  114. // _Must_inspect_result_ expands into this
  115. #define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD \
  116. __declspec( \
  117. "SAL_name" \
  118. "(" \
  119. "\"_Must_inspect_result_\"" \
  120. "," \
  121. "\"\"" \
  122. "," \
  123. "\"2\"" \
  124. ")") __declspec("SAL_begin") __declspec("SAL_post") __declspec("SAL_mustInspect") __declspec("SAL_post") __declspec("SAL_checkReturn") __declspec("SAL_end")
  125. #endif
  126. #endif
  127. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
  128. #define BOOST_OUTCOME_SYSTEM_ERROR2_NODISCARD
  129. #endif
  130. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI
  131. #if defined(BOOST_OUTCOME_STANDARDESE_IS_IN_THE_HOUSE) || (__clang_major__ >= 7 && !defined(__APPLE__))
  132. //! Defined to be `[[clang::trivial_abi]]` when on a new enough clang compiler. Usually automatic, can be overriden.
  133. #define BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI [[clang::trivial_abi]]
  134. #else
  135. #define BOOST_OUTCOME_SYSTEM_ERROR2_TRIVIAL_ABI
  136. #endif
  137. #endif
  138. #if defined(__cpp_concepts) && !defined(BOOST_OUTCOME_SYSTEM_ERROR2_DISABLE_CONCEPTS_SUPPORT)
  139. #define BOOST_OUTCOME_SYSTEM_ERROR2_GLUE(x, y) x y
  140. #define BOOST_OUTCOME_SYSTEM_ERROR2_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, count, ...) count
  141. #define BOOST_OUTCOME_SYSTEM_ERROR2_EXPAND_ARGS(args) BOOST_OUTCOME_SYSTEM_ERROR2_RETURN_ARG_COUNT args
  142. #define BOOST_OUTCOME_SYSTEM_ERROR2_COUNT_ARGS_MAX8(...) BOOST_OUTCOME_SYSTEM_ERROR2_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
  143. #define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO2(name, count) name##count
  144. #define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO1(name, count) BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO2(name, count)
  145. #define BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO(name, count) BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO1(name, count)
  146. #define BOOST_OUTCOME_SYSTEM_ERROR2_CALL_OVERLOAD(name, ...) BOOST_OUTCOME_SYSTEM_ERROR2_GLUE(BOOST_OUTCOME_SYSTEM_ERROR2_OVERLOAD_MACRO(name, BOOST_OUTCOME_SYSTEM_ERROR2_COUNT_ARGS_MAX8(__VA_ARGS__)), (__VA_ARGS__))
  147. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND8(a, b, c, d, e, f, g, h) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND7(b, c, d, e, f, g, h)
  148. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND7(a, b, c, d, e, f, g) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND6(b, c, d, e, f, g)
  149. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND6(a, b, c, d, e, f) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND5(b, c, d, e, f)
  150. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND5(a, b, c, d, e) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND4(b, c, d, e)
  151. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND4(a, b, c, d) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND3(b, c, d)
  152. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND3(a, b, c) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND2(b, c)
  153. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND2(a, b) a &&BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND1(b)
  154. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND1(a) a
  155. //! Expands into a && b && c && ...
  156. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(...) requires BOOST_OUTCOME_SYSTEM_ERROR2_CALL_OVERLOAD(BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES_EXPAND, __VA_ARGS__)
  157. #define BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(...) template <__VA_ARGS__>
  158. #define BOOST_OUTCOME_SYSTEM_ERROR2_TEXPR(...) \
  159. requires { (__VA_ARGS__); }
  160. #define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) (__VA_ARGS__)
  161. #if !defined(_MSC_VER) || _MSC_FULL_VER >= 192400000 // VS 2019 16.3 is broken here
  162. #define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...) requires(__VA_ARGS__)
  163. #else
  164. #define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...)
  165. #endif
  166. #else
  167. #define BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(...) template <__VA_ARGS__
  168. #define BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(...) , __VA_ARGS__ >
  169. #define BOOST_OUTCOME_SYSTEM_ERROR2_TEXPR(...) typename = decltype(__VA_ARGS__)
  170. #ifdef _MSC_VER
  171. // MSVC gives an error if every specialisation of a template is always ill-formed, so
  172. // the more powerful SFINAE form below causes pukeage :(
  173. #define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) typename = typename std::enable_if<(__VA_ARGS__)>::type
  174. #else
  175. #define BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(...) typename std::enable_if<(__VA_ARGS__), bool>::type = true
  176. #endif
  177. #define BOOST_OUTCOME_SYSTEM_ERROR2_REQUIRES(...)
  178. #endif
  179. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE
  180. //! The system_error2 namespace name.
  181. #define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE system_error2
  182. //! Begins the system_error2 namespace.
  183. #define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN \
  184. namespace system_error2 \
  185. {
  186. //! Ends the system_error2 namespace.
  187. #define BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END }
  188. #endif
  189. //! Namespace for the library
  190. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
  191. //! Namespace for user specialised traits
  192. namespace traits
  193. {
  194. /*! Specialise to true if you guarantee that a type is move bitcopying (i.e.
  195. its move constructor equals copying bits from old to new, old is left in a
  196. default constructed state, and calling the destructor on a default constructed
  197. instance is trivial). All trivially copyable types are move bitcopying by
  198. definition, and that is the unspecialised implementation.
  199. */
  200. template <class T> struct is_move_bitcopying
  201. {
  202. static constexpr bool value = std::is_trivially_copyable<T>::value;
  203. };
  204. } // namespace traits
  205. namespace detail
  206. {
  207. #if __cplusplus >= 201400 || _MSC_VER >= 1910 /* VS2017 */
  208. inline constexpr size_t cstrlen(const char *str)
  209. {
  210. const char *end = nullptr;
  211. for(end = str; *end != 0; ++end) // NOLINT
  212. ;
  213. return end - str;
  214. }
  215. #else
  216. inline constexpr size_t cstrlen_(const char *str, size_t acc) { return (str[0] == 0) ? acc : cstrlen_(str + 1, acc + 1); }
  217. inline constexpr size_t cstrlen(const char *str) { return cstrlen_(str, 0); }
  218. #endif
  219. #if(__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && __cpp_lib_remove_cvref >= 201711L
  220. template <class T> using remove_cvref = std::remove_cvref<T>;
  221. #else
  222. template <class T> struct remove_cvref
  223. {
  224. using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
  225. };
  226. #endif
  227. /* A partially compliant implementation of C++20's std::bit_cast function contributed
  228. by Jesse Towner.
  229. Our bit_cast is only guaranteed to be constexpr when both the input and output
  230. arguments are either integrals or enums. However, this covers most use cases
  231. since the vast majority of status_codes have an underlying type that is either
  232. an integral or enum. We still attempt a constexpr union-based type pun for non-array
  233. input types, which some compilers accept. For array inputs, we fall back to
  234. non-constexpr memmove.
  235. */
  236. template <class T> using is_integral_or_enum = std::integral_constant<bool, std::is_integral<T>::value || std::is_enum<T>::value>;
  237. 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>;
  238. template <class To, class From>
  239. using is_union_castable = std::integral_constant<bool, !is_static_castable<To, From>::value && !std::is_array<To>::value && !std::is_array<From>::value>;
  240. template <class To, class From>
  241. using is_bit_castable =
  242. std::integral_constant<bool, sizeof(To) == sizeof(From) && traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
  243. template <class To, class From> union bit_cast_union
  244. {
  245. From source;
  246. To target;
  247. };
  248. #if BOOST_OUTCOME_SYSTEM_ERROR2_HAVE_BIT_CAST
  249. using std::bit_cast; // available for all trivially copyable types
  250. // For move bit copying types
  251. template <class To, class From>
  252. requires(is_bit_castable<To, From>::value //
  253. &&is_union_castable<To, From>::value //
  254. && (!std::is_trivially_copyable_v<From> //
  255. || !std::is_trivially_copyable_v<To>) ) //
  256. constexpr To bit_cast(const From &from) noexcept
  257. {
  258. return bit_cast_union<To, From>{from}.target;
  259. }
  260. template <class To, class From>
  261. requires(is_bit_castable<To, From>::value //
  262. && !is_union_castable<To, From>::value //
  263. && (!std::is_trivially_copyable_v<From> //
  264. || !std::is_trivially_copyable_v<To>) ) //
  265. To bit_cast(const From &from)
  266. noexcept
  267. {
  268. bit_cast_union<To, From> ret;
  269. memmove(&ret.source, &from, sizeof(ret.source));
  270. return ret.target;
  271. }
  272. #else
  273. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, int = 5)
  274. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
  275. &&is_static_castable<To, From>::value //
  276. && !is_union_castable<To, From>::value))
  277. constexpr To bit_cast(const From &from) noexcept { return static_cast<To>(from); }
  278. #if defined(__GNUC__) && !defined(__clang__)
  279. #pragma GCC diagnostic push
  280. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  281. #endif
  282. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, long = 5)
  283. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
  284. && !is_static_castable<To, From>::value //
  285. && is_union_castable<To, From>::value))
  286. constexpr To bit_cast(const From &from) noexcept { return bit_cast_union<To, From>{from}.target; }
  287. #if defined(__GNUC__) && !defined(__clang__)
  288. #pragma GCC diagnostic pop
  289. #endif
  290. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
  291. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_bit_castable<To, From>::value //
  292. && !is_static_castable<To, From>::value //
  293. && !is_union_castable<To, From>::value))
  294. To bit_cast(const From &from) noexcept
  295. {
  296. bit_cast_union<To, From> ret;
  297. memmove(&ret.source, &from, sizeof(ret.source));
  298. return ret.target;
  299. }
  300. #endif
  301. /* erasure_cast performs a bit_cast with additional rules to handle types
  302. of differing sizes. For integral & enum types, it may perform a narrowing
  303. or widing conversion with static_cast if necessary, before doing the final
  304. conversion with bit_cast. When casting to or from non-integral, non-enum
  305. types it may insert the value into another object with extra padding bytes
  306. to satisfy bit_cast's preconditions that both types have the same size. */
  307. template <class To, class From>
  308. using is_erasure_castable = std::integral_constant<bool, traits::is_move_bitcopying<To>::value && traits::is_move_bitcopying<From>::value>;
  309. template <class T, bool = std::is_enum<T>::value> struct identity_or_underlying_type
  310. {
  311. using type = T;
  312. };
  313. template <class T> struct identity_or_underlying_type<T, true>
  314. {
  315. using type = typename std::underlying_type<T>::type;
  316. };
  317. template <class OfSize, class OfSign>
  318. using erasure_integer_type = typename std::conditional<std::is_signed<typename identity_or_underlying_type<OfSign>::type>::value,
  319. typename std::make_signed<typename identity_or_underlying_type<OfSize>::type>::type,
  320. typename std::make_unsigned<typename identity_or_underlying_type<OfSize>::type>::type>::type;
  321. template <class ErasedType, std::size_t N> struct padded_erasure_object
  322. {
  323. static_assert(traits::is_move_bitcopying<ErasedType>::value, "ErasedType must be TriviallyCopyable or MoveBitcopying");
  324. static_assert(alignof(ErasedType) <= sizeof(ErasedType), "ErasedType must not be over-aligned");
  325. ErasedType value;
  326. char padding[N];
  327. constexpr explicit padded_erasure_object(const ErasedType &v) noexcept
  328. : value(v)
  329. , padding{}
  330. {
  331. }
  332. };
  333. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From)
  334. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) == sizeof(From))))
  335. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(from); }
  336. #if defined(_WIN32) || defined(__APPLE__) || __LITTLE_ENDIAN__ || (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN)
  337. // We can avoid the type pun on little endian architectures which can aid optimisation
  338. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, long = 5)
  339. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value &&is_static_castable<To, From>::value && (sizeof(To) < sizeof(From))))
  340. constexpr To erasure_cast(const From &from) noexcept { return static_cast<To>(bit_cast<erasure_integer_type<From, To>>(from)); }
  341. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, int = 5)
  342. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value &&is_static_castable<To, From>::value && (sizeof(To) > sizeof(From))))
  343. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(static_cast<erasure_integer_type<To, From>>(from)); }
  344. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
  345. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) < sizeof(From))))
  346. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value; }
  347. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, char = 5)
  348. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && !is_static_castable<To, From>::value && (sizeof(To) > sizeof(From))))
  349. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from}); }
  350. #else
  351. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, short = 5)
  352. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) < sizeof(From))))
  353. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<padded_erasure_object<To, sizeof(From) - sizeof(To)>>(from).value; }
  354. BOOST_OUTCOME_SYSTEM_ERROR2_TEMPLATE(class To, class From, char = 5)
  355. BOOST_OUTCOME_SYSTEM_ERROR2_TREQUIRES(BOOST_OUTCOME_SYSTEM_ERROR2_TPRED(is_erasure_castable<To, From>::value && (sizeof(To) > sizeof(From))))
  356. constexpr To erasure_cast(const From &from) noexcept { return bit_cast<To>(padded_erasure_object<From, sizeof(To) - sizeof(From)>{from}); }
  357. #endif
  358. } // namespace detail
  359. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
  360. #ifndef BOOST_OUTCOME_SYSTEM_ERROR2_FATAL
  361. #ifdef BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX
  362. #error If BOOST_OUTCOME_SYSTEM_ERROR2_NOT_POSIX is defined, you must define your own BOOST_OUTCOME_SYSTEM_ERROR2_FATAL implementation!
  363. #endif
  364. #include <cstdlib> // for abort
  365. #ifdef __APPLE__
  366. #include <unistd.h> // for write
  367. #endif
  368. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_BEGIN
  369. namespace detail
  370. {
  371. namespace avoid_stdio_include
  372. {
  373. #if !defined(__APPLE__) && !defined(_MSC_VER)
  374. extern "C" ptrdiff_t write(int, const void *, size_t);
  375. #elif defined(_MSC_VER)
  376. extern ptrdiff_t write(int, const void *, size_t);
  377. #if(defined(__x86_64__) || defined(_M_X64)) || (defined(__aarch64__) || defined(_M_ARM64)) || (defined(__arm__) || defined(_M_ARM))
  378. #pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YA_JHPEBX_K@Z=write")
  379. #elif defined(__x86__) || defined(_M_IX86) || defined(__i386__)
  380. #pragma comment(linker, "/alternatename:?write@avoid_stdio_include@detail@system_error2@@YAHHPBXI@Z=_write")
  381. #else
  382. #error Unknown architecture
  383. #endif
  384. #endif
  385. } // namespace avoid_stdio_include
  386. inline void do_fatal_exit(const char *msg)
  387. {
  388. using namespace avoid_stdio_include;
  389. write(2 /*stderr*/, msg, cstrlen(msg));
  390. write(2 /*stderr*/, "\n", 1);
  391. abort();
  392. }
  393. } // namespace detail
  394. BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE_END
  395. //! Prints msg to stderr, and calls `std::terminate()`. Can be overriden via predefinition.
  396. #define BOOST_OUTCOME_SYSTEM_ERROR2_FATAL(msg) ::BOOST_OUTCOME_SYSTEM_ERROR2_NAMESPACE::detail::do_fatal_exit(msg)
  397. #endif
  398. #endif