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"
76 template <
typename F,
typename... Args>
78 {
noexcept (f (args...)) };
90 template <
typename F,
typename R,
typename... Args>
91 concept invocable_r = invocable<F, Args...> && convertible_to<invoke_result_t<F, Args...>, R>;
92 static_assert (
invocable_r<
decltype ([] (int) {
return ""; }),
const char*,
int>);
93 static_assert (
invocable_r<
decltype ([] (
char*,
char*) {}),
void,
char*,
char*>);
98 requires { []<
typename Rep,
typename Period> (type_identity<chrono::duration<Rep, Period>>) {}(type_identity<T> ()); };
99 static_assert (not IDuration<float>);
102 template <
typename T>
104 requires { []<
typename CLOCK,
typename DURATION> (type_identity<chrono::time_point<CLOCK, DURATION>>) {}(type_identity<T> ()); };
105 static_assert (not ITimePoint<float>);
119 template <
typename T,
typename... U>
125 template <
typename T>
132 template <
typename...>
144 template <
class _Ty1,
class _Ty2>
146 { __x == __y } -> Boolean_testable;
147 { __x != __y } -> Boolean_testable;
149 static_assert (not equality_comparable_with<nullopt_t, optional<int>>);
154 template <
typename OT>
155 concept IOptional = same_as<remove_cvref_t<OT>, optional<typename OT::value_type>>;
156 static_assert (IOptional<optional<int>>);
157 static_assert (not IOptional<int>);
160#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
161 template <
typename T1,
typename T2 =
void>
162 struct is_shared_ptr_ : false_type {};
163 template <
typename T1>
164 struct is_shared_ptr_<shared_ptr<T1>> : true_type {};
165 template <
typename T1,
typename T2 =
void>
166 struct is_pair_ : false_type {};
167 template <
typename T1,
typename T2>
168 struct is_pair_<pair<T1, T2>> : true_type {};
169 template <
typename... ARGS>
170 struct is_variant_ : false_type {};
171 template <
typename... ARGS>
172 struct is_variant_<variant<ARGS...>> : true_type {};
179 template <
typename T>
181#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
182 Private_::is_pair_<T>::value
186 []<
typename T1,
typename T2> (pair<T1, T2>) {}(t)
195 template <
typename T>
197#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
198 Private_::is_shared_ptr_<T>::value
203 []<
typename T1> (shared_ptr<T1>) {}(t)
212 template <
typename T,
size_t N>
213 concept has_tuple_element =
requires (T t) {
214 typename tuple_element_t<N, remove_const_t<T>>;
215 { get<N> (t) } -> convertible_to<const tuple_element_t<N, T>&>;
224 template <
typename T>
225 concept ITuple = !is_reference_v<T> &&
requires (T t) {
226 typename tuple_size<T>::type;
227 requires derived_from<tuple_size<T>, integral_constant<size_t, tuple_size_v<T>>>;
228 } && []<
size_t... N> (index_sequence<N...>) {
return (Private_::has_tuple_element<T, N> && ...); }(make_index_sequence<tuple_size_v<T>> ());
233 template <
typename T>
235#if qCompilerAndStdLib_template_concept_matcher_requires_Buggy
236 Private_::is_variant_<T>::value
240 []<
typename... TYPES> (variant<TYPES...>) {}(t)
255 template <
typename T>
257 template <
typename TEST_ARGUMENT>
258 using Test = conditional_t<convertible_to<TEST_ARGUMENT, T>, true_type, false_type>;
268 template <
typename T>
270 template <
typename TEST_ARGUMENT>
271 using Test = conditional_t<constructible_from<TEST_ARGUMENT, T>, true_type, false_type>;
285 template <
typename T>
287 { t.size () } -> convertible_to<size_t>;
291 template <
typename T>
292 concept HasEq_ =
requires (T t) {
293 { t == t } -> convertible_to<bool>;
295 template <
typename T>
296 constexpr inline bool HasEq_v_ = HasEq_<T>;
297 template <
typename T,
typename U>
298 constexpr inline bool HasEq_v_<pair<T, U>> = HasEq_v_<T> and HasEq_v_<U>;
299 template <
typename... Ts>
300 constexpr inline bool HasEq_v_<tuple<Ts...>> = (HasEq_v_<Ts> and ...);
301 template <
typename T>
302 constexpr bool HasUsableEqualToOptimization ()
308 if constexpr (Private_::HasEq_v_<T>) {
309 struct EqualToEmptyTester_ : equal_to<T> {
313 return sizeof (EqualToEmptyTester_) ==
sizeof (
int);
323 template <
typename T>
338 template <
typename T>
342 template <
typename T,
typename =
void>
343 struct ExtractValueType {
346 template <IHasValueType T>
347 struct ExtractValueType<T> {
348 using type =
typename T::value_type;
350 template <
typename T>
351 struct ExtractValueType<const T*,
void> {
354 template <
typename T>
355 struct ExtractValueType<T*,
void> {
369 template <
typename T>
375 template <
typename T>
387 template <
bool B,
typename T>
389 static constexpr bool value = B;
392 template <
typename HEAD,
typename... TAIL>
393 struct Select : conditional_t<HEAD::value, HEAD, Select<TAIL...>> {};
394 template <
typename T>
398 template <
bool B,
typename T>
399 struct Select<Case<B, T>> {
401 static_assert (B,
"!");
404 template <
typename HEAD,
typename... TAIL>
405 using Select_t =
typename Select<HEAD, TAIL...>::type;
414#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...