emlabcpp
modern opinionated embedded C++ library
concepts.h
Go to the documentation of this file.
1 
24 #pragma once
25 
26 #include "./types/base.h"
27 
28 #include <concepts>
29 #include <iterator>
30 #include <variant>
31 
32 namespace emlabcpp
33 {
34 
37 
38 template < typename T >
39 concept additive_operators = requires( T a, T b ) {
40  { a + b } -> std::convertible_to< T >;
41  { a - b } -> std::convertible_to< T >;
42 };
43 
44 template < typename T >
45 concept multiplicative_operators = requires( T a, T b ) {
46  { a / b } -> std::convertible_to< T >;
47  { a* b } -> std::convertible_to< T >;
48 };
49 
50 template < typename T >
51 concept arithmetic_operators = additive_operators< T > && multiplicative_operators< T >;
52 
53 template < typename T >
54 concept arithmetic_assignment = requires( T a, T b ) {
55  { a += b };
56  { a -= b };
57  { a /= b };
58  { a *= b };
59 };
60 
61 template < typename T >
62 concept arithmetic_like = arithmetic_operators< T > && arithmetic_assignment< T >;
63 
64 template < typename T >
65 concept arithmetic = std::integral< T > || std::floating_point< T >;
66 
69 
70 template < typename T >
71 concept gettable_container = requires( T a ) {
72  { std::tuple_size< std::decay_t< T > >::value } -> std::convertible_to< std::size_t >;
73 };
74 
77 template < typename T >
78 concept range_container =
79  ( (
80  requires( T a ) { begin( a ); } || requires( T a ) { std::begin( a ); } ) &&
81  (
82  requires( T a ) { end( a ); } || requires( T a ) { std::end( a ); } ) ) ||
83  std::is_bounded_array_v< T >;
84 
85 template < typename T >
86 concept data_container =
87  (
88  requires( T a ) { data( a ); } || requires( T a ) { std::data( a ); } ) &&
89  (
90  requires( T a ) { size( a ); } || requires( T a ) { std::size( a ); } );
91 
92 template < typename T >
93 concept container = range_container< T > || gettable_container< T > || data_container< T >;
94 
95 template < typename T >
97  is_view< T >::value || ( range_container< T > && !std::is_rvalue_reference_v< T > );
98 
99 template < typename T, typename ValueType >
101  range_container< T > && std::same_as< typename T::value_type, ValueType >;
102 
103 template < typename T, typename Iterator >
105  range_container< T > && std::convertible_to< iterator_of_t< T >, Iterator >;
106 
107 template < typename T, typename ValueType >
109  data_container< T > && std::same_as< typename T::value_type, ValueType >;
110 
111 template < typename T, typename DataIterator >
113  data_container< T > && std::convertible_to< data_iterator_of_t< T >, DataIterator >;
114 
115 template < typename T >
116 concept static_sized = requires( T a ) {
117  { std::tuple_size< std::decay_t< T > >::value } -> std::convertible_to< std::size_t >;
118 };
119 
122 
123 template < typename UnaryCallable, typename Container >
125  requires( Container cont, UnaryCallable f ) { f( *cont.begin() ); } ||
126  requires( Container cont ) { std::tuple_size< std::decay_t< Container > >::value == 0; } ||
127  requires( Container cont, UnaryCallable f ) {
131  f( std::get< 0 >( cont ) );
132  };
133 
134 template < typename UnaryCallable, typename ReturnValue, typename... Args >
136  { f( args... ) } -> std::same_as< ReturnValue >;
137 };
138 
141 
142 namespace detail
143 {
144  template < typename Stream, typename T >
145  concept directly_streamable_for = requires( Stream os, T val ) { os.operator<<( val ); };
146 } // namespace detail
147 
148 template < typename T >
149 concept ostreamlike = !std::is_array_v< T > && requires( T val ) {
150  requires detail::directly_streamable_for< T, uint8_t >;
151  requires detail::directly_streamable_for< T, uint16_t >;
152  requires detail::directly_streamable_for< T, uint32_t >;
153  requires detail::directly_streamable_for< T, int8_t >;
154  requires detail::directly_streamable_for< T, int16_t >;
155  requires detail::directly_streamable_for< T, int32_t >;
156  requires detail::directly_streamable_for< T, float >;
157  requires detail::directly_streamable_for< T, double >;
158  requires detail::directly_streamable_for< T, bool >;
159  requires detail::directly_streamable_for< T, void const* >;
160  requires detail::directly_streamable_for< T, std::nullptr_t >;
161 };
162 
163 template < typename T >
164 concept ostreamable = requires( std::ostream& os, T item ) {
165  { os << item } -> std::convertible_to< std::ostream& >;
166 };
167 
169 
171 template < typename T, typename Variant >
172 concept alternative_of = []< typename... Ts >( std::variant< Ts... >* ) {
173  return ( std::same_as< T, Ts > || ... );
174 }( static_cast< Variant* >( nullptr ) );
175 
176 template < typename T, typename Tuple >
177 concept element_of = []< typename... Ts >( std::tuple< Ts... >* ) {
178  return ( std::same_as< T, Ts > || ... );
179 }( static_cast< Tuple* >( nullptr ) );
180 
181 template < typename T >
182 concept with_value_type = requires { typename T::value_type; };
183 
184 template < typename T, typename Signature >
185 concept with_signature = std::same_as< typename signature_of< T >::signature, Signature >;
186 
187 template < typename T >
188 concept with_push_back =
189  requires( T a, typename T::value_type b ) { a.push_back( std::move( b ) ); };
190 
191 template < typename T, typename U >
192 concept some = std::same_as< std::remove_cv_t< T >, U >;
193 
194 } // namespace emlabcpp
concept directly_streamable_for
Definition: concepts.h:145
std::variant< int64_t, float, bool, string_buffer > value_type
Definition: base.h:51
MIT License.
Definition: impl.h:31
concept additive_operators
Definition: concepts.h:39
constexpr pointer data() noexcept
Returns pointer to first item of the storage.
Definition: static_storage.h:108
concept with_push_back
Definition: concepts.h:188
concept ostreamlike
Definition: concepts.h:149
concept element_of
Definition: concepts.h:177
concept data_container_with_iter
Definition: concepts.h:112
concept invocable_returning
Definition: concepts.h:135
concept arithmetic_like
Definition: concepts.h:62
concept alternative_of
Thanks for the solution goes to PJBoy@libera.
Definition: concepts.h:172
Args const & args
Definition: min_max.h:83
concept multiplicative_operators
Definition: concepts.h:45
concept some
Definition: concepts.h:192
concept data_container_with
Definition: concepts.h:108
concept arithmetic
Definition: concepts.h:65
concept data_container
Definition: concepts.h:86
concept static_sized
Definition: concepts.h:116
concept range_container
so, std::ranges::range is meh because it expects return of begin() being input_output_iterator,...
Definition: concepts.h:78
concept arithmetic_operators
Definition: concepts.h:51
concept ostreamable
Definition: concepts.h:164
concept arithmetic_assignment
Definition: concepts.h:54
requires(!range_container< Container >) const expr std
Returns index of an element in tuple 't', for which call to predicate f(x) holds true,...
Definition: algorithm.h:127
concept container_invocable
Definition: concepts.h:124
concept range_container_with_iter
Definition: concepts.h:104
UnaryCallable
Definition: types.h:54
concept container
Definition: concepts.h:93
concept referenceable_container
Definition: concepts.h:96
concept gettable_container
Definition: concepts.h:71
concept range_container_with
Definition: concepts.h:100
UnaryCallable && f
Definition: algorithm.h:161
concept with_value_type
Definition: concepts.h:182
concept with_signature
Definition: concepts.h:185
Definition: base.h:79