//// Copyright (c) 2019-2021 Kris Jusiak (kris at jusiak dot net)//// Distributed under the Boost Software License, Version 1.0.// (See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//#if defined(__cpp_modules) && !defined(BOOST_UT_DISABLE_MODULE)export module boost.ut;export import std;#define BOOST_UT_EXPORT export#else#pragma once#define BOOST_UT_EXPORT#endif #if __has_include(<iso646.h>)#include <iso646.h> // and, or, not, ...#endif #include <version>#if defined(_MSC_VER) #pragma push_macro("min") #pragma push_macro("max") #undef min #undef max#endif// Before libc++ 17 had experimental support for format and it required a// special build flag. Currently libc++ has not implemented all C++20 chrono// improvements. Therefore doesn't define __cpp_lib_format, instead query the// library version to detect the support status.//// MSVC STL and libstdc++ provide __cpp_lib_format.#if defined(__cpp_lib_format) or \ (defined(_LIBCPP_VERSION) and _LIBCPP_VERSION >= 170000)#define BOOST_UT_HAS_FORMAT#endif #if not defined(__cpp_rvalue_references)#error "[Boost::ext].UT requires support for rvalue references";#elif not defined(__cpp_decltype)#error "[Boost::ext].UT requires support for decltype";#elif not defined(__cpp_return_type_deduction)#error "[Boost::ext].UT requires support for return type deduction";#elif not defined(__cpp_deduction_guides)#error "[Boost::ext].UT requires support for return deduction guides";#elif not defined(__cpp_generic_lambdas)#error "[Boost::ext].UT requires support for generic lambdas";#elif not defined(__cpp_constexpr)#error "[Boost::ext].UT requires support for constexpr";#elif not defined(__cpp_alias_templates)#error "[Boost::ext].UT requires support for alias templates";#elif not defined(__cpp_variadic_templates)#error "[Boost::ext].UT requires support for variadic templates";#elif not defined(__cpp_fold_expressions)#error "[Boost::ext].UT requires support for return fold expressions";#elif not defined(__cpp_static_assert)#error "[Boost::ext].UT requires support for static assert";#else#define BOOST_UT_VERSION 2'0'1 #if defined(__has_builtin) and defined(__GNUC__) and (__GNUC__ < 10) and \ not defined(__clang__)#undef __has_builtin#endif #if not defined(__has_builtin)#if defined(__GNUC__) and (__GNUC__ >= 9)#define __has___builtin_FILE 1#define __has___builtin_LINE 1#endif#define __has_builtin(...) __has_##__VA_ARGS__#endif #include <algorithm>#include <array>#include <chrono>#include <concepts>#include <cstdint>#include <functional>#include <iostream>#include <memory>#include <optional>#include <sstream>#include <stack>#include <string_view>#include <type_traits>#include <unordered_map>#include <utility>#include <variant>#include <vector>#include <fstream>#if __has_include(<unistd.h>) and __has_include(<sys/wait.h>)#include <sys/wait.h>#include <unistd.h>#endif#if defined(__cpp_exceptions)#include <exception>#endif #if __has_include(<format>)#include <format>#endif#if __has_include(<source_location>)#include <source_location>#endif struct unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_ {}; BOOST_UT_EXPORTnamespace boost::inline ext::ut::inline v2_0_1 {namespace utility {template <class>class function;template <class R, class... TArgs>class function<R(TArgs...)> { public: constexpr function() = default; template <class T> constexpr /*explicit(false)*/ function(T data) : invoke_{invoke_impl<T>}, destroy_{destroy_impl<T>}, data_{new T{static_cast<T&&>(data)}} {} constexpr function(function&& other) noexcept : invoke_{static_cast<decltype(other.invoke_)&&>(other.invoke_)}, destroy_{static_cast<decltype(other.destroy_)&&>(other.destroy_)}, data_{static_cast<decltype(other.data_)&&>(other.data_)} { other.data_ = {}; } constexpr function(const function&) = delete; ~function() { destroy_(data_); } constexpr function& operator=(const function&) = delete; constexpr function& operator=(function&&) = delete; [[nodiscard]] constexpr auto operator()(TArgs... args) -> R { return invoke_(data_, args...); } [[nodiscard]] constexpr auto operator()(TArgs... args) const -> R { return invoke_(data_, args...); } private: template <class T> [[nodiscard]] static auto invoke_impl(void* data, TArgs... args) -> R { return (*static_cast<T*>(data))(args...); } template <class T> static auto destroy_impl(void* data) -> void { delete static_cast<T*>(data); } R (*invoke_)(void*, TArgs...){}; void (*destroy_)(void*){}; void* data_{};}; [[nodiscard]] inline auto is_match(std::string_view input, std::string_view pattern) -> bool { if (std::empty(pattern)) { return std::empty(input); } if (std::empty(input)) { return pattern[0] == '*' ? is_match(input, pattern.substr(1)) : false; } if (pattern[0] != '?' and pattern[0] != '*' and pattern[0] != input[0]) { return false; } if (pattern[0] == '*') { for (decltype(std::size(input)) i = 0u; i <= std::size(input); ++i) { if (is_match(input.substr(i), pattern.substr(1))) { return true; } } return false; } return is_match(input.substr(1), pattern.substr(1));} template <class TPattern, class TStr>[[nodiscard]] constexpr auto match(const TPattern& pattern, const TStr& str) -> std::vector<TStr> { std::vector<TStr> groups{}; auto pi = 0u; auto si = 0u; const auto matcher = [&](char b, char e, char c = 0) { const auto match = si; while (str[si] and str[si] != b and str[si] != c) { ++si; } groups.emplace_back(str.substr(match, si - match)); while (pattern[pi] and pattern[pi] != e) { ++pi; } pi++; }; while (pi < std::size(pattern) && si < std::size(str)) { if (pattern[pi] == '\'' and str[si] == '\'' and pattern[pi + 1] == '{') { ++si; matcher('\'', '}'); } else if (pattern[pi] == '{') { matcher(' ', '}', ','); } else if (pattern[pi] != str[si]) { return {}; } ++pi; ++si; } if (si < str.size() or pi < std::size(pattern)) { return {}; } return groups;} template <class T = std::string_view, class TDelim>[[nodiscard]] inline auto split(T input, TDelim delim) -> std::vector<T> { std::vector<T> output{}; std::size_t first{}; while (first < std::size(input)) { const auto second = input.find_first_of(delim, first); if (first != second) { output.emplace_back(input.substr(first, second - first)); } if (second == T::npos) { break; } first = second + 1; } return output;}constexpr auto regex_match(const char *str, const char *pattern) -> bool { if (*pattern == '\0' && *str == '\0') return true; if (*pattern == '\0' && *str != '\0') return false; if (*str == '\0' && *pattern != '\0') return false; if (*pattern == '.') { return regex_match(str+1, pattern+1); } if (*pattern == *str) { return regex_match(str+1, pattern+1); } return false;}} // namespace utility namespace reflection {#if defined(__cpp_lib_source_location)using source_location = std::source_location;#elseclass source_location { public: [[nodiscard]] static constexpr auto current(#if (__has_builtin(__builtin_FILE) and __has_builtin(__builtin_LINE)) const char* file = __builtin_FILE(), int line = __builtin_LINE()#else const char* file = "unknown", int line = {}#endif ) noexcept { source_location sl{}; sl.file_ = file; sl.line_ = line; return sl; } [[nodiscard]] constexpr auto file_name() const noexcept { return file_; } [[nodiscard]] constexpr auto line() const noexcept { return line_; } private: const char* file_{"unknown"}; int line_{};};#endifnamespace detail {template <typename TargetType>[[nodiscard]] constexpr auto get_template_function_name_use_type() -> const std::string_view {// for over compiler need over macros#if defined(_MSC_VER) && !defined(__clang__) return {&__FUNCSIG__[0], sizeof(__FUNCSIG__)};#else return {&__PRETTY_FUNCTION__[0], sizeof(__PRETTY_FUNCTION__)};#endif} // decay allows you to highlight a cleaner nametemplate <typename TargetType>[[nodiscard]] constexpr auto get_template_function_name_use_decay_type() -> const std::string_view { return get_template_function_name_use_type<std::decay_t<TargetType>>();} inline constexpr const std::string_view raw_type_name = get_template_function_name_use_decay_type< unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_>(); inline constexpr const std::size_t raw_length = raw_type_name.length();inline constexpr const std::string_view need_name =#if defined(_MSC_VER) and not defined(__clang__) "struct " "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_";#else "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_";#endifinline constexpr const std::size_t need_length = need_name.length();static_assert(need_length <= raw_length, "Auto find prefix and suffix lenght broken error 1");inline constexpr const std::size_t prefix_length = raw_type_name.find(need_name);static_assert(prefix_length != std::string_view::npos, "Auto find prefix and suffix lenght broken error 2");static_assert(prefix_length <= raw_length, "Auto find prefix and suffix lenght broken error 3");inline constexpr const std::size_t tail_lenght = raw_length - prefix_length;static_assert(need_length <= tail_lenght, "Auto find prefix and suffix lenght broken error 4");inline constexpr const std::size_t suffix_length = tail_lenght - need_length; } // namespace detail template <typename TargetType>[[nodiscard]] constexpr auto type_name() -> const std::string_view { const std::string_view raw_type_name = detail::get_template_function_name_use_type<TargetType>(); const std::size_t end = raw_type_name.length() - detail::suffix_length; const std::size_t len = end - detail::prefix_length; std::string_view result = raw_type_name.substr(detail::prefix_length, len); return result;} // decay allows you to highlight a cleaner nametemplate <typename TargetType>[[nodiscard]] constexpr auto decay_type_name() -> const std::string_view { const std::string_view raw_type_name = detail::get_template_function_name_use_decay_type<TargetType>(); const std::size_t end = raw_type_name.length() - detail::suffix_length; const std::size_t len = end - detail::prefix_length; std::string_view result = raw_type_name.substr(detail::prefix_length, len); return result;}} // namespace reflection namespace math {template <class T>[[nodiscard]] constexpr auto abs(const T t) -> T { return t < T{} ? -t : t;} template <class T, class U>[[nodiscard]] constexpr auto abs_diff(const T t, const U u) -> decltype(t < u ? u - t : t - u) { return t < u ? u - t : t - u;} template <class T>[[nodiscard]] constexpr auto min_value(const T& lhs, const T& rhs) -> const T& { return (rhs < lhs) ? rhs : lhs;} template <class T, class TExp>[[nodiscard]] constexpr auto pow(const T base, const TExp exp) -> T { return exp ? T(base * pow(base, exp - TExp(1))) : T(1);} template <class T, char... Cs>[[nodiscard]] constexpr auto num() -> T { static_assert( ((Cs == '.' or Cs == '\'' or (Cs >= '0' and Cs <= '9')) and ...)); T result{}; for (const char c : std::array{Cs...}) { if (c == '.') { break; } if (c >= '0' and c <= '9') { result = result * T(10) + T(c - '0'); } } return result;} template <class T, char... Cs>[[nodiscard]] constexpr auto den() -> T { constexpr const std::array cs{Cs...}; T result{}; auto i = 0u; while (cs[i++] != '.') { } for (auto j = i; j < sizeof...(Cs); ++j) { result += pow(T(10), sizeof...(Cs) - j) * T(cs[j] - '0'); } return result;} template <class T, char... Cs>[[nodiscard]] constexpr auto den_size() -> T { constexpr const std::array cs{Cs...}; T i{}; while (cs[i++] != '.') { } return T(sizeof...(Cs)) - i + T(1);} template <class T, class TValue>[[nodiscard]] constexpr auto den_size(TValue value) -> T { constexpr auto precision = TValue(1e-7); T result{}; TValue tmp{}; do { value *= 10; tmp = value - T(value); ++result; } while (tmp > precision); return result;} } // namespace math namespace type_traits {template <class...>struct list {}; template <class T, class...>struct identity { using type = T;}; template <class T>struct function_traits : function_traits<decltype(&T::operator())> {}; template <class R, class... TArgs>struct function_traits<R (*)(TArgs...)> { using result_type = R; using args = list<TArgs...>;}; template <class R, class... TArgs>struct function_traits<R(TArgs...)> { using result_type = R; using args = list<TArgs...>;}; template <class R, class T, class... TArgs>struct function_traits<R (T::*)(TArgs...)> { using result_type = R; using args = list<TArgs...>;}; template <class R, class T, class... TArgs>struct function_traits<R (T::*)(TArgs...) const> { using result_type = R; using args = list<TArgs...>;}; template <class T>T&& declval();template <class... Ts, class TExpr>constexpr auto is_valid(TExpr expr) -> decltype(expr(declval<Ts...>()), bool()) { return true;}template <class...>constexpr auto is_valid(...) -> bool { return false;} template <class T>inline constexpr auto is_range_v = is_valid<T>([](auto t) -> decltype(t.begin(), t.end(), void()) {}); template <class T>inline constexpr auto has_user_print = is_valid<T>( [](auto t) -> decltype(void(declval<std::ostringstream&>() << t)) {}); template <class T, class = void>struct has_static_member_object_value : std::false_type {}; template <class T>struct has_static_member_object_value<T, std::void_t<decltype(declval<T>().value)>> : std::bool_constant<!std::is_member_pointer_v<decltype(&T::value)> && !std::is_function_v<decltype(T::value)>> {}; template <class T>inline constexpr bool has_static_member_object_value_v = has_static_member_object_value<T>::value; template <class T, class = void>struct has_static_member_object_epsilon : std::false_type {}; template <class T>struct has_static_member_object_epsilon<Lines 1–500 of 3346. Load more
// // Copyright (c) 2019-2021 Kris Jusiak (kris at jusiak dot net) // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #if defined(__cpp_modules) && !defined(BOOST_UT_DISABLE_MODULE) export module boost.ut; export import std; #define BOOST_UT_EXPORT export #else #pragma once #define BOOST_UT_EXPORT #endif #if __has_include(<iso646.h>) #include <iso646.h> // and, or, not, ... #endif #include <version> #if defined(_MSC_VER) #pragma push_macro("min") #pragma push_macro("max") #undef min #undef max #endif // Before libc++ 17 had experimental support for format and it required a // special build flag. Currently libc++ has not implemented all C++20 chrono // improvements. Therefore doesn't define __cpp_lib_format, instead query the // library version to detect the support status. // // MSVC STL and libstdc++ provide __cpp_lib_format. #if defined(__cpp_lib_format) or \ (defined(_LIBCPP_VERSION) and _LIBCPP_VERSION >= 170000) #define BOOST_UT_HAS_FORMAT #endif #if not defined(__cpp_rvalue_references) #error "[Boost::ext].UT requires support for rvalue references"; #elif not defined(__cpp_decltype) #error "[Boost::ext].UT requires support for decltype"; #elif not defined(__cpp_return_type_deduction) #error "[Boost::ext].UT requires support for return type deduction"; #elif not defined(__cpp_deduction_guides) #error "[Boost::ext].UT requires support for return deduction guides"; #elif not defined(__cpp_generic_lambdas) #error "[Boost::ext].UT requires support for generic lambdas"; #elif not defined(__cpp_constexpr) #error "[Boost::ext].UT requires support for constexpr"; #elif not defined(__cpp_alias_templates) #error "[Boost::ext].UT requires support for alias templates"; #elif not defined(__cpp_variadic_templates) #error "[Boost::ext].UT requires support for variadic templates"; #elif not defined(__cpp_fold_expressions) #error "[Boost::ext].UT requires support for return fold expressions"; #elif not defined(__cpp_static_assert) #error "[Boost::ext].UT requires support for static assert"; #else #define BOOST_UT_VERSION 2'0'1 #if defined(__has_builtin) and defined(__GNUC__) and (__GNUC__ < 10) and \ not defined(__clang__) #undef __has_builtin #endif #if not defined(__has_builtin) #if defined(__GNUC__) and (__GNUC__ >= 9) #define __has___builtin_FILE 1 #define __has___builtin_LINE 1 #endif #define __has_builtin(...) __has_##__VA_ARGS__ #endif #include <algorithm> #include <array> #include <chrono> #include <concepts> #include <cstdint> #include <functional> #include <iostream> #include <memory> #include <optional> #include <sstream> #include <stack> #include <string_view> #include <type_traits> #include <unordered_map> #include <utility> #include <variant> #include <vector> #include <fstream> #if __has_include(<unistd.h>) and __has_include(<sys/wait.h>) #include <sys/wait.h> #include <unistd.h> #endif #if defined(__cpp_exceptions) #include <exception> #endif #if __has_include(<format>) #include <format> #endif #if __has_include(<source_location>) #include <source_location> #endif struct unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_ { }; BOOST_UT_EXPORT namespace boost::inline ext::ut::inline v2_0_1 { namespace utility { template <class> class function; template <class R, class... TArgs> class function<R(TArgs...)> { public: constexpr function() = default; template <class T> constexpr /*explicit(false)*/ function(T data) : invoke_{invoke_impl<T>}, destroy_{destroy_impl<T>}, data_{new T{static_cast<T&&>(data)}} {} constexpr function(function&& other) noexcept : invoke_{static_cast<decltype(other.invoke_)&&>(other.invoke_)}, destroy_{static_cast<decltype(other.destroy_)&&>(other.destroy_)}, data_{static_cast<decltype(other.data_)&&>(other.data_)} { other.data_ = {}; } constexpr function(const function&) = delete; ~function() { destroy_(data_); } constexpr function& operator=(const function&) = delete; constexpr function& operator=(function&&) = delete; [[nodiscard]] constexpr auto operator()(TArgs... args) -> R { return invoke_(data_, args...); } [[nodiscard]] constexpr auto operator()(TArgs... args) const -> R { return invoke_(data_, args...); } private: template <class T> [[nodiscard]] static auto invoke_impl(void* data, TArgs... args) -> R { return (*static_cast<T*>(data))(args...); } template <class T> static auto destroy_impl(void* data) -> void { delete static_cast<T*>(data); } R (*invoke_)(void*, TArgs...){}; void (*destroy_)(void*){}; void* data_{}; }; [[nodiscard]] inline auto is_match(std::string_view input, std::string_view pattern) -> bool { if (std::empty(pattern)) { return std::empty(input); } if (std::empty(input)) { return pattern[0] == '*' ? is_match(input, pattern.substr(1)) : false; } if (pattern[0] != '?' and pattern[0] != '*' and pattern[0] != input[0]) { return false; } if (pattern[0] == '*') { for (decltype(std::size(input)) i = 0u; i <= std::size(input); ++i) { if (is_match(input.substr(i), pattern.substr(1))) { return true; } } return false; } return is_match(input.substr(1), pattern.substr(1)); } template <class TPattern, class TStr> [[nodiscard]] constexpr auto match(const TPattern& pattern, const TStr& str) -> std::vector<TStr> { std::vector<TStr> groups{}; auto pi = 0u; auto si = 0u; const auto matcher = [&](char b, char e, char c = 0) { const auto match = si; while (str[si] and str[si] != b and str[si] != c) { ++si; } groups.emplace_back(str.substr(match, si - match)); while (pattern[pi] and pattern[pi] != e) { ++pi; } pi++; }; while (pi < std::size(pattern) && si < std::size(str)) { if (pattern[pi] == '\'' and str[si] == '\'' and pattern[pi + 1] == '{') { ++si; matcher('\'', '}'); } else if (pattern[pi] == '{') { matcher(' ', '}', ','); } else if (pattern[pi] != str[si]) { return {}; } ++pi; ++si; } if (si < str.size() or pi < std::size(pattern)) { return {}; } return groups; } template <class T = std::string_view, class TDelim> [[nodiscard]] inline auto split(T input, TDelim delim) -> std::vector<T> { std::vector<T> output{}; std::size_t first{}; while (first < std::size(input)) { const auto second = input.find_first_of(delim, first); if (first != second) { output.emplace_back(input.substr(first, second - first)); } if (second == T::npos) { break; } first = second + 1; } return output; } constexpr auto regex_match(const char *str, const char *pattern) -> bool { if (*pattern == '\0' && *str == '\0') return true; if (*pattern == '\0' && *str != '\0') return false; if (*str == '\0' && *pattern != '\0') return false; if (*pattern == '.') { return regex_match(str+1, pattern+1); } if (*pattern == *str) { return regex_match(str+1, pattern+1); } return false; } } // namespace utility namespace reflection { #if defined(__cpp_lib_source_location) using source_location = std::source_location; #else class source_location { public: [[nodiscard]] static constexpr auto current( #if (__has_builtin(__builtin_FILE) and __has_builtin(__builtin_LINE)) const char* file = __builtin_FILE(), int line = __builtin_LINE() #else const char* file = "unknown", int line = {} #endif ) noexcept { source_location sl{}; sl.file_ = file; sl.line_ = line; return sl; } [[nodiscard]] constexpr auto file_name() const noexcept { return file_; } [[nodiscard]] constexpr auto line() const noexcept { return line_; } private: const char* file_{"unknown"}; int line_{}; }; #endif namespace detail { template <typename TargetType> [[nodiscard]] constexpr auto get_template_function_name_use_type() -> const std::string_view { // for over compiler need over macros #if defined(_MSC_VER) && !defined(__clang__) return {&__FUNCSIG__[0], sizeof(__FUNCSIG__)}; #else return {&__PRETTY_FUNCTION__[0], sizeof(__PRETTY_FUNCTION__)}; #endif } // decay allows you to highlight a cleaner name template <typename TargetType> [[nodiscard]] constexpr auto get_template_function_name_use_decay_type() -> const std::string_view { return get_template_function_name_use_type<std::decay_t<TargetType>>(); } inline constexpr const std::string_view raw_type_name = get_template_function_name_use_decay_type< unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_>(); inline constexpr const std::size_t raw_length = raw_type_name.length(); inline constexpr const std::string_view need_name = #if defined(_MSC_VER) and not defined(__clang__) "struct " "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_"; #else "unique_name_for_auto_detect_prefix_and_suffix_lenght_0123456789_struct_"; #endif inline constexpr const std::size_t need_length = need_name.length(); static_assert(need_length <= raw_length, "Auto find prefix and suffix lenght broken error 1"); inline constexpr const std::size_t prefix_length = raw_type_name.find(need_name); static_assert(prefix_length != std::string_view::npos, "Auto find prefix and suffix lenght broken error 2"); static_assert(prefix_length <= raw_length, "Auto find prefix and suffix lenght broken error 3"); inline constexpr const std::size_t tail_lenght = raw_length - prefix_length; static_assert(need_length <= tail_lenght, "Auto find prefix and suffix lenght broken error 4"); inline constexpr const std::size_t suffix_length = tail_lenght - need_length; } // namespace detail template <typename TargetType> [[nodiscard]] constexpr auto type_name() -> const std::string_view { const std::string_view raw_type_name = detail::get_template_function_name_use_type<TargetType>(); const std::size_t end = raw_type_name.length() - detail::suffix_length; const std::size_t len = end - detail::prefix_length; std::string_view result = raw_type_name.substr(detail::prefix_length, len); return result; } // decay allows you to highlight a cleaner name template <typename TargetType> [[nodiscard]] constexpr auto decay_type_name() -> const std::string_view { const std::string_view raw_type_name = detail::get_template_function_name_use_decay_type<TargetType>(); const std::size_t end = raw_type_name.length() - detail::suffix_length; const std::size_t len = end - detail::prefix_length; std::string_view result = raw_type_name.substr(detail::prefix_length, len); return result; } } // namespace reflection namespace math { template <class T> [[nodiscard]] constexpr auto abs(const T t) -> T { return t < T{} ? -t : t; } template <class T, class U> [[nodiscard]] constexpr auto abs_diff(const T t, const U u) -> decltype(t < u ? u - t : t - u) { return t < u ? u - t : t - u; } template <class T> [[nodiscard]] constexpr auto min_value(const T& lhs, const T& rhs) -> const T& { return (rhs < lhs) ? rhs : lhs; } template <class T, class TExp> [[nodiscard]] constexpr auto pow(const T base, const TExp exp) -> T { return exp ? T(base * pow(base, exp - TExp(1))) : T(1); } template <class T, char... Cs> [[nodiscard]] constexpr auto num() -> T { static_assert( ((Cs == '.' or Cs == '\'' or (Cs >= '0' and Cs <= '9')) and ...)); T result{}; for (const char c : std::array{Cs...}) { if (c == '.') { break; } if (c >= '0' and c <= '9') { result = result * T(10) + T(c - '0'); } } return result; } template <class T, char... Cs> [[nodiscard]] constexpr auto den() -> T { constexpr const std::array cs{Cs...}; T result{}; auto i = 0u; while (cs[i++] != '.') { } for (auto j = i; j < sizeof...(Cs); ++j) { result += pow(T(10), sizeof...(Cs) - j) * T(cs[j] - '0'); } return result; } template <class T, char... Cs> [[nodiscard]] constexpr auto den_size() -> T { constexpr const std::array cs{Cs...}; T i{}; while (cs[i++] != '.') { } return T(sizeof...(Cs)) - i + T(1); } template <class T, class TValue> [[nodiscard]] constexpr auto den_size(TValue value) -> T { constexpr auto precision = TValue(1e-7); T result{}; TValue tmp{}; do { value *= 10; tmp = value - T(value); ++result; } while (tmp > precision); return result; } } // namespace math namespace type_traits { template <class...> struct list {}; template <class T, class...> struct identity { using type = T; }; template <class T> struct function_traits : function_traits<decltype(&T::operator())> {}; template <class R, class... TArgs> struct function_traits<R (*)(TArgs...)> { using result_type = R; using args = list<TArgs...>; }; template <class R, class... TArgs> struct function_traits<R(TArgs...)> { using result_type = R; using args = list<TArgs...>; }; template <class R, class T, class... TArgs> struct function_traits<R (T::*)(TArgs...)> { using result_type = R; using args = list<TArgs...>; }; template <class R, class T, class... TArgs> struct function_traits<R (T::*)(TArgs...) const> { using result_type = R; using args = list<TArgs...>; }; template <class T> T&& declval(); template <class... Ts, class TExpr> constexpr auto is_valid(TExpr expr) -> decltype(expr(declval<Ts...>()), bool()) { return true; } template <class...> constexpr auto is_valid(...) -> bool { return false; } template <class T> inline constexpr auto is_range_v = is_valid<T>([](auto t) -> decltype(t.begin(), t.end(), void()) {}); template <class T> inline constexpr auto has_user_print = is_valid<T>( [](auto t) -> decltype(void(declval<std::ostringstream&>() << t)) {}); template <class T, class = void> struct has_static_member_object_value : std::false_type {}; template <class T> struct has_static_member_object_value<T, std::void_t<decltype(declval<T>().value)>> : std::bool_constant<!std::is_member_pointer_v<decltype(&T::value)> && !std::is_function_v<decltype(T::value)>> {}; template <class T> inline constexpr bool has_static_member_object_value_v = has_static_member_object_value<T>::value; template <class T, class = void> struct has_static_member_object_epsilon : std::false_type {}; template <class T> struct has_static_member_object_epsilon<