4#ifndef _Stroika_Foundation_Common_StdCompat_h_
5#define _Stroika_Foundation_Common_StdCompat_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
17#if defined(__cpp_lib_expected)
28#if qStroika_HasComponent_fmtlib
29#include <fmt/chrono.h>
30#include <fmt/format.h>
32#elif __has_include(<format>)
55namespace Stroika::Foundation::Common::StdCompat {
79 { lo.lock () } -> std::same_as<void>;
81 { lo.unlock () } -> std::same_as<void>;
97 { lo.try_lock () } -> std::same_as<bool>;
113 template <
typename T>
114 concept TimedLockable =
Lockable<T> and
requires (T lo,
const chrono::milliseconds& d,
const chrono::time_point<chrono::steady_clock>& tp) {
116 { lo.try_lock_for (d) } -> std::same_as<bool>;
118 { lo.try_lock_until (tp) } -> std::same_as<bool>;
135 template <
typename T>
137 TimedLockable<T> and default_initializable<T> and destructible<T> and not copy_constructible<T> and not move_constructible<T>;
141 concept _Boolean_testable_impl = convertible_to<_Ty, bool>;
151 { !
static_cast<_Ty&&
> (__t) } -> Private_::_Boolean_testable_impl;
159 template <
class FROM,
class TO>
162#if qStroika_HasComponent_fmtlib
163#define qStroika_Foundation_Characters_FMT_PREFIX_ fmt
164#elif __has_include(<format>)
165#define qStroika_Foundation_Characters_FMT_PREFIX_ std
167 static_assert (
false,
"Stroika v3 requires some std::format compatible library - if building with one lacking builtin std::format, "
168 "configure --fmtlib use");
175 using qStroika_Foundation_Characters_FMT_PREFIX_::basic_format_parse_context;
176 using qStroika_Foundation_Characters_FMT_PREFIX_::format;
177 using qStroika_Foundation_Characters_FMT_PREFIX_::format_args;
178 using qStroika_Foundation_Characters_FMT_PREFIX_::format_error;
179 using qStroika_Foundation_Characters_FMT_PREFIX_::format_string;
180 using qStroika_Foundation_Characters_FMT_PREFIX_::format_to;
181 using qStroika_Foundation_Characters_FMT_PREFIX_::make_format_args;
182 using qStroika_Foundation_Characters_FMT_PREFIX_::make_wformat_args;
183 using qStroika_Foundation_Characters_FMT_PREFIX_::vformat;
184 using qStroika_Foundation_Characters_FMT_PREFIX_::wformat_args;
185 using qStroika_Foundation_Characters_FMT_PREFIX_::wformat_string;
187#if qStroika_Foundation_Common_cplusplus >= qStroika_Foundation_Common_cplusplus_23
188 template <
class T,
class CharT>
189 concept formattable = std::formattable<T, CharT>;
192 template <
class _CharT>
193 struct _Phony_fmt_iter_for {
194 using difference_type = ptrdiff_t;
195 _CharT& operator* ()
const;
196 _Phony_fmt_iter_for& operator++ ();
197 _Phony_fmt_iter_for operator++ (
int);
202 template <
class _Ty,
class _Context,
class _Formatter = qStroika_Foundation_Characters_FMT_PREFIX_::formatter<remove_const_t<_Ty>,
typename _Context::
char_type>>
203 concept _Formattable_with = semiregular<_Formatter> &&
requires (_Formatter& __f,
const _Formatter& __cf, _Ty&& __t, _Context __fc,
204 basic_format_parse_context<typename _Context::char_type> __pc) {
205 { __f.parse (__pc) } -> same_as<
typename decltype (__pc)::iterator>;
206 { __cf.format (__t, __fc) } -> same_as<typename _Context::iterator>;
209 template <
class T,
class CharT>
210 concept formattable =
211 Private_::_Formattable_with<remove_reference_t<T>, qStroika_Foundation_Characters_FMT_PREFIX_::basic_format_context<Private_::_Phony_fmt_iter_for<CharT>, CharT>>;
224#if defined(__cpp_lib_byteswap)
230 static_assert (std::has_unique_object_representations_v<T>,
"T may not have padding bits");
231 auto value_representation = bit_cast<array<byte,
sizeof (T)>> (n);
232 for (
size_t i = 0; i < value_representation.size () / 2; ++i) {
233 swap (value_representation[i], value_representation[value_representation.size () - 1 - i]);
235 return bit_cast<T> (value_representation);
242 template <
typename T>
243#if qStroika_Foundation_Common_cplusplus >= qStroika_Foundation_Common_cplusplus_23
250 return std::isinf (v);
256 template <
typename T>
257#if qStroika_Foundation_Common_cplusplus >= qStroika_Foundation_Common_cplusplus_23
264 return std::isnan (v);
267#if qCompilerAndStdLib_stdlib_compare_three_way_present_but_Buggy
268 struct compare_three_way {
270 template <
typename LT,
typename RT>
271 constexpr auto operator() (LT&& lhs, RT&& rhs)
const
273 using CT = common_type_t<LT, RT>;
274 if (equal_to<CT>{}(forward<LT> (lhs), forward<RT> (rhs))) {
275 return strong_ordering::equal;
277 return less<CT>{}(forward<LT> (lhs), forward<RT> (rhs)) ? strong_ordering::less : strong_ordering::greater;
279 using is_transparent = void;
282 using compare_three_way = std::compare_three_way;
288#if defined(__cpp_lib_expected)
289 template <
typename T>
290 using unexpected = std::unexpected<T>;
291 template <
typename T,
typename E>
292 using expected = std::expected<T, E>;
294 template <
typename T>
297 template <
typename _UError = T>
298 requires (!is_same_v<remove_cvref_t<_UError>,
unexpected> && !is_same_v<remove_cvref_t<_UError>, in_place_t> && is_constructible_v<T, _UError>)
299 constexpr explicit unexpected (_UError&& _Unex)
300 : _Unexpected (forward<_UError> (_Unex))
303 template <
typename... _Args>
304 requires is_constructible_v<T, _Args...>
305 constexpr explicit unexpected (in_place_t, _Args&&... _Vals)
306 : _Unexpected (forward<_Args> (_Vals)...)
309 template <
typename _Uty,
typename... _Args>
310 requires is_constructible_v<T, initializer_list<_Uty>&, _Args...>
311 constexpr explicit unexpected (in_place_t, initializer_list<_Uty> _Ilist, _Args&&... _Vals)
312 : _Unexpected (_Ilist, forward<_Args> (_Vals)...)
316 constexpr const T& error ()
const&
noexcept
320 constexpr T& error () &
noexcept
324 constexpr const T&& error ()
const&&
noexcept
326 return std::move (_Unexpected);
328 constexpr T&& error () &&
noexcept
330 return std::move (_Unexpected);
336 swap (_Unexpected, _Other._Unexpected);
340 requires is_swappable<T>::value
345 template <
class _UErr>
348 return _Left._Unexpected == _Right.error ();
354 template <
typename T>
363 template <
typename T,
typename E>
365 template <
typename T,
typename E>
368 using value_type = T;
369 using error_type = E;
372 constexpr expected ()
noexcept =
default;
382 template <
typename T1,
typename E1>
392 explicit operator bool ()
const noexcept
394 return std::get_if<T> (&fData_) !=
nullptr;
402 return get<T> (fData_);
406 return get<E> (fData_);
410 variant<T, E> fData_;
425#if __has_cpp_attribute(indeterminate)
426#define Stroika_ATTRIBUTE_INDETERMINATE [[indeterminate]]
428#define Stroika_ATTRIBUTE_INDETERMINATE
437#if __has_cpp_attribute(assume) && defined(__clang__)
442#define Stroika_ATTRIBUTE_ASSUME(X) \
443 _Pragma ("clang diagnostic push") _Pragma ("clang diagnostic ignored \"-Wassume\"") [[assume (X)]]; \
444 _Pragma ("clang diagnostic pop")
445#elif __has_cpp_attribute(assume)
446#define Stroika_ATTRIBUTE_ASSUME(X) [[assume (X)]];
451#define Stroika_ATTRIBUTE_ASSUME(X) __assume (X);
453#define Stroika_ATTRIBUTE_ASSUME(X)
462#if qCompilerAndStdLib_NO_UNIQUE_ADDR_IgnoredAndMustUseMSVCNOUNIQUE_Buggy && defined(_MSC_VER)
463#if qCompilerAndStdLib_NO_UNIQUE_ADDR_REALLYREALLY_Buggy
464#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
466#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
468#elif __has_cpp_attribute(no_unique_address)
469#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
471#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
478#if qCompilerAndStdLib_NO_UNIQUE_ADDR_REALLYREALLY_Buggy
479#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE [[msvc::no_unique_address]]
481#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
490#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCBUGGY Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
494#define qStroika_ATTRIBUTE_INDETERMINATE Stroika_ATTRIBUTE_INDETERMINATE
495#define qStroika_ATTRIBUTE_ASSUME Stroika_ATTRIBUTE_ASSUME
496#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS
497#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
498#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCBUGGY Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCBUGGY
507#include "StdCompat.inl"
constexpr bool isnan(T v) noexcept
constexpr bool isinf(T v) noexcept
Logically the C++ standard BasicLockable named requirement, but that was not included in std c++ libr...
handy re-usable concept, with the obvious meaning, and strangely omitted from std-c++ (though used in...
Logically the C++ standard Lockable named requirement, but that was not included in std c++ library.
Logically the C++ standard TimedLockable named requirement, but that was not included in std c++ libr...
Logically the C++ standard TimedMutex named requirement, but that was not included in std c++ library...
like convertible_to, but also handling cases where T has an explicit CTOR taking From