4#ifndef _Stroika_Foundation_Common_Concept_h_
5#define _Stroika_Foundation_Common_Concept_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
18#include "Stroika/Foundation/Common/Common.h"
19#include "Stroika/Foundation/Common/ConceptsBase.h"
102 template <
typename T>
104 template <
typename CLASS_TYPE,
typename RETURN_TYPE,
typename... ARGS>
105 struct FunctionTraits<RETURN_TYPE (CLASS_TYPE::*) (ARGS...) const> {
109 static inline constexpr size_t kArity =
sizeof...(ARGS);
114 using result_type = RETURN_TYPE;
125 using type =
typename tuple_element<i, tuple<ARGS...>>::type;
133 using arg_t =
typename arg<i>::type;
141 using type =
typename conditional_t<(i <
sizeof...(ARGS)), tuple_element<i, tuple<ARGS...>>, Private_::void_type>::type;
147 using ArgOrVoid_t =
typename ArgOrVoid<i>::type;
153 template <
typename F,
typename... Args>
155 {
noexcept (f (args...)) };
167 template <
typename F,
typename R,
typename... Args>
168 concept invocable_r = invocable<F, Args...> && convertible_to<invoke_result_t<F, Args...>, R>;
169 static_assert (
invocable_r<
decltype ([] (int) {
return ""; }),
const char*,
int>);
170 static_assert (
invocable_r<
decltype ([] (
char*,
char*) {}),
void,
char*,
char*>);
173 template <
typename T>
175 requires { []<
typename Rep,
typename Period> (type_identity<chrono::duration<Rep, Period>>) {}(type_identity<T> ()); };
176 static_assert (not IDuration<float>);
179 template <
typename T>
181 requires { []<
typename CLOCK,
typename DURATION> (type_identity<chrono::time_point<CLOCK, DURATION>>) {}(type_identity<T> ()); };
182 static_assert (not ITimePoint<float>);
196 template <
typename T,
typename... U>
202 template <
typename T>
209 template <
typename...>
221 template <
class _Ty1,
class _Ty2>
223 { __x == __y } -> Boolean_testable;
224 { __x != __y } -> Boolean_testable;
226 static_assert (not equality_comparable_with<nullopt_t, optional<int>>);
231 template <
typename OT>
232 concept IOptional = same_as<remove_cvref_t<OT>, optional<typename OT::value_type>>;
233 static_assert (IOptional<optional<int>>);
234 static_assert (not IOptional<int>);
237#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
238 template <
typename T1,
typename T2 =
void>
239 struct is_shared_ptr_ : false_type {};
240 template <
typename T1>
241 struct is_shared_ptr_<shared_ptr<T1>> : true_type {};
242 template <
typename T1,
typename T2 =
void>
243 struct is_pair_ : false_type {};
244 template <
typename T1,
typename T2>
245 struct is_pair_<pair<T1, T2>> : true_type {};
246 template <
typename... ARGS>
247 struct is_variant_ : false_type {};
248 template <
typename... ARGS>
249 struct is_variant_<variant<ARGS...>> : true_type {};
256 template <
typename T>
258#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
259 Private_::is_pair_<T>::value
263 []<
typename T1,
typename T2> (pair<T1, T2>) {}(t)
272 template <
typename T>
274#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
275 Private_::is_shared_ptr_<T>::value
280 []<
typename T1> (shared_ptr<T1>) {}(t)
289 template <
typename T,
size_t N>
290 concept has_tuple_element =
requires (T t) {
291 typename tuple_element_t<N, remove_const_t<T>>;
292 { get<N> (t) } -> convertible_to<const tuple_element_t<N, T>&>;
301 template <
typename T>
302 concept ITuple = !is_reference_v<T> &&
requires (T t) {
303 typename tuple_size<T>::type;
304 requires derived_from<tuple_size<T>, integral_constant<size_t, tuple_size_v<T>>>;
305 } && []<
size_t... N> (index_sequence<N...>) {
return (Private_::has_tuple_element<T, N> && ...); }(make_index_sequence<tuple_size_v<T>> ());
310 template <
typename T>
312#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
313 Private_::is_variant_<T>::value
317 []<
typename... TYPES> (variant<TYPES...>) {}(t)
332 template <
typename T>
334 template <
typename TEST_ARGUMENT>
335 using Test = conditional_t<convertible_to<TEST_ARGUMENT, T>, true_type, false_type>;
345 template <
typename T>
347 template <
typename TEST_ARGUMENT>
348 using Test = conditional_t<constructible_from<TEST_ARGUMENT, T>, true_type, false_type>;
362 template <
typename T>
364 { t.size () } -> convertible_to<size_t>;
368 template <
typename T>
369 concept HasEq_ =
requires (T t) {
370 { t == t } -> convertible_to<bool>;
372 template <
typename T>
373 constexpr inline bool HasEq_v_ = HasEq_<T>;
374 template <
typename T,
typename U>
375 constexpr inline bool HasEq_v_<pair<T, U>> = HasEq_v_<T> and HasEq_v_<U>;
376 template <
typename... Ts>
377 constexpr inline bool HasEq_v_<tuple<Ts...>> = (HasEq_v_<Ts> and ...);
378 template <
typename T>
379 constexpr bool HasUsableEqualToOptimization ()
385 if constexpr (Private_::HasEq_v_<T>) {
386 struct EqualToEmptyTester_ : equal_to<T> {
390 return sizeof (EqualToEmptyTester_) ==
sizeof (
int);
400 template <
typename T>
415 template <
typename T>
419 template <
typename T,
typename =
void>
420 struct ExtractValueType {
423 template <IHasValueType T>
424 struct ExtractValueType<T> {
425 using type =
typename T::value_type;
427 template <
typename T>
428 struct ExtractValueType<const T*,
void> {
431 template <
typename T>
432 struct ExtractValueType<T*,
void> {
446 template <
typename T>
452 template <
typename T>
464 template <
bool B,
typename T>
466 static constexpr bool value = B;
469 template <
typename HEAD,
typename... TAIL>
470 struct Select : conditional_t<HEAD::value, HEAD, Select<TAIL...>> {};
471 template <
typename T>
475 template <
bool B,
typename T>
476 struct Select<Case<B, T>> {
478 static_assert (B,
"!");
481 template <
typename HEAD,
typename... TAIL>
482 using Select_t =
typename Select<HEAD, TAIL...>::type;
491#include "Concepts.inl"
concept - trivial shorthand for variadic same_as A or same_as B, or ...
concept true if integral or floating-point type 'T'. Not sure why not provided by std c++
check T has had remove_cvref_t called on it (e.g. ICVRefTd<const string&> is string)
Concept checks if the given type T has a const size() method which can be called to return a size_t.
Concept checks if the given type T has a value_type (type) member.
like std::invocable concept, except also requires the invocation doesn't raise exceptions
return true iff argument type T, is std::pair<a,b> for some a/b types
return true iff argument type T, is std::shared_ptr<A> for some A types
Concept ITuple<T> check if T is a tuple.
detect if T is a std::variant<> type.
handy re-usable concept, with the obvious meaning, and strangely omitted from std-c++ (though used in...
like convertible_to, but also handling cases where T has an explicit CTOR taking From
equality_comparable_with, but less strict - just checks if it can be equality compared!
concept version of std::is_trivially_copyable_v
typename Private_::ExtractValueType< remove_cvref_t< T > >::type ExtractValueType_t
Extract the type of elements in a container, or returned by an iterator (value_type) or void it there...
Extract the number of arguments, return type, and each individual argument type from a lambda or simp...