#pragma once #include #include #include namespace mcc::traits { template concept mcc_char_view = std::ranges::view && std::same_as, char>; // input range of char/const char template concept mcc_input_char_range = std::ranges::input_range && std::is_same_v>, CharT>; // output range of char/const char template concept mcc_output_char_range = std::ranges::output_range && std::same_as>, CharT>; template concept mcc_view_or_output_char_range = mcc_char_view || mcc_output_char_range; template concept mcc_range_of_input_char_range = std::ranges::range && traits::mcc_input_char_range>; template concept mcc_range_of_output_char_range = std::ranges::range && traits::mcc_output_char_range>; // https://stackoverflow.com/questions/72430369/how-to-check-that-a-type-is-formattable-using-type-traits-concepts) template concept mcc_formattable = requires(T v, std::format_context ctx) { std::formatter>().format(v, ctx); }; // from https://stackoverflow.com/questions/74383254/concept-that-models-only-the-stdchrono-duration-types template concept mcc_time_duration_c = requires { [](std::type_identity>) { }(std::type_identity>()); }; template concept mcc_systime_c = requires { [](std::type_identity>) {}(std::type_identity>()); }; /* a callable concept and its signature traits */ template concept mcc_is_callable = std::is_function_v || (std::is_object_v && requires(T) { &T::operator(); }); // helper classes for callable signature deducing template struct mcc_func_traits_helper_t; template struct mcc_func_traits_helper_t { using ret_t = R; using args_t = std::tuple<>; using arg1_t = void; static constexpr size_t arity = 0; }; template struct mcc_func_traits_helper_t { using ret_t = R; using args_t = std::tuple; using arg1_t = Arg; static constexpr size_t arity = sizeof...(Args) + 1; }; template struct mcc_func_traits { // use of an empty struct here to match std::invoke_result behaivior (at least of GCC) }; template struct mcc_func_traits : mcc_func_traits_helper_t { }; template struct mcc_func_traits : mcc_func_traits_helper_t { }; template struct mcc_func_traits : mcc_func_traits_helper_t { }; template struct mcc_func_traits : mcc_func_traits_helper_t { }; template requires mcc_is_callable struct mcc_func_traits : mcc_func_traits { }; // reference/const ref and rvalue helpers template struct mcc_func_traits : mcc_func_traits { }; template struct mcc_func_traits : mcc_func_traits { }; template struct mcc_func_traits : mcc_func_traits { }; template using mcc_retval_t = typename mcc_func_traits::ret_t; template using mcc_func_arg1_t = typename mcc_func_traits::arg1_t; } // namespace mcc::traits