SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
utility/container/concept.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024 Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024 Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#include <concepts>
13#include <initializer_list>
14#include <iterator>
15#include <type_traits>
16
18
19#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
20# include <string>
21
22namespace seqan3::detail
23{
24
28template <typename basic_string_t>
29struct is_basic_string : std::false_type
30{};
31
35template <typename value_t, typename traits_t, typename allocator_t>
36struct is_basic_string<std::basic_string<value_t, traits_t, allocator_t>> : std::true_type
37{};
38
42template <typename basic_string_t>
43constexpr bool is_basic_string_v = is_basic_string<basic_string_t>::value;
44
45} // namespace seqan3::detail
46#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
47
48namespace seqan3
49{
50
69template <typename type>
70concept container = requires (type val, type val2, type const cval, typename type::iterator it) {
71 // member types
72 typename type::value_type;
73 typename type::reference;
74 typename type::const_reference;
75 /*
76 typename type::iterator;
77 requires std::forward_iterator<typename type::iterator>;
78 // NOTE check whether iterator is const convertible
79 {it} -> std::same_as<typename type::const_iterator>;
80
81 typename type::const_iterator;
82 requires std::forward_iterator<typename type::const_iterator>;
83
84 typename type::difference_type;
85 typename type::size_type;
86 requires std::is_same_v<
87 typename type::difference_type,
88 typename std::iterator_traits<typename type::iterator>::difference_type
89 >;
90 requires std::is_same_v<
91 typename std::iterator_traits<typename type::iterator>::difference_type,
92 typename std::iterator_traits<typename type::const_iterator>::difference_type
93 >;
94*/
95 // methods and operator
96 {
97 type{}
98 } -> std::same_as<type>; // default constructor
99 {
100 type{type{}}
101 } -> std::same_as<type>; // copy/move constructor
102 {
103 val = val2
104 } -> std::same_as<type &>; // assignment
105 {
106 (&val)->~type()
107 }; // destructor
108
109 {
110 val.begin()
111 } -> std::same_as<typename type::iterator>;
112 {
113 val.end()
114 } -> std::same_as<typename type::iterator>;
115 {
116 cval.begin()
117 } -> std::same_as<typename type::const_iterator>;
118 {
119 cval.end()
120 } -> std::same_as<typename type::const_iterator>;
121 {
122 val.cbegin()
123 } -> std::same_as<typename type::const_iterator>;
124 {
125 val.cend()
126 } -> std::same_as<typename type::const_iterator>;
127
128 requires !std::equality_comparable<typename type::value_type> || std::equality_comparable<type>;
129
130 {
131 val.swap(val2)
132 } -> std::same_as<void>;
133 {
134 swap(val, val2)
135 } -> std::same_as<void>;
136 {
137 std::swap(val, val2)
138 } -> std::same_as<void>;
139
140 {
141 val.size()
142 } -> std::same_as<typename type::size_type>;
143 {
144 val.max_size()
145 } -> std::same_as<typename type::size_type>;
146 {
147 val.empty()
148 } -> std::same_as<bool>;
149 };
151
168template <typename type>
169concept sequence_container =
170 requires (type val, type val2, type const cval) {
171 requires container<type>;
172
173 // construction
174 {
175 type(typename type::size_type{}, typename type::value_type{})
176 };
177 {
178 type{val2.begin(), val2.end()}
179 }; // NOTE that this could be any input iterator:
180 {
182 };
183 {
185 } -> std::same_as<type &>;
186
187 // assignment NOTE return type is type & for std::string and void for other stl containers:
188 {
189 val.assign(val2.begin(), val2.end())
190 };
191 {
193 };
194 {
195 val.assign(typename type::size_type{}, typename type::value_type{})
196 };
197
198 // modify container
199 // TODO: how do you model this?
200 // {val.emplace(typename type::const_iterator{}, ?)} -> std::same_as<typename type::iterator>;
201#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
202 {
203 val.insert(val.begin(), val2.front())
204 } -> std::same_as<typename type::iterator>;
205 {
206 val.insert(val.begin(), typename type::value_type{})
207 } -> std::same_as<typename type::iterator>;
208
209 // std::string is missing the const_iterator versions for insert in pre-C++11 ABI
210 requires detail::is_basic_string_v<type>
211 || requires (type val, type val2)
212#else // ^^^ workaround / no workaround vvv
213 requires requires (type val, type val2)
214#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
215 {
216 {
217 val.insert(val.cbegin(), val2.front())
218 } -> std::same_as<typename type::iterator>;
219 {
220 val.insert(val.cbegin(), typename type::value_type{})
221 } -> std::same_as<typename type::iterator>;
222 {
223 val.insert(val.cbegin(), typename type::size_type{}, typename type::value_type{})
224 } -> std::same_as<typename type::iterator>;
225 {
226 val.insert(val.cbegin(), val2.begin(), val2.end())
227 } -> std::same_as<typename type::iterator>;
228 {
229 val.insert(val.cbegin(), std::initializer_list<typename type::value_type>{})
230 } -> std::same_as<typename type::iterator>;
231 };
232
233#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
234 // std::string is missing the const_iterator versions for erase in pre-C++11 ABI
235 requires detail::is_basic_string_v<type>
236 || requires (type val)
237#else // ^^^ workaround / no workaround vvv
238 requires requires (type val)
239#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
240 {
241 {
242 val.erase(val.cbegin())
243 } -> std::same_as<typename type::iterator>;
244 {
245 val.erase(val.cbegin(), val.cend())
246 } -> std::same_as<typename type::iterator>;
247 };
248
249 {
250 val.push_back(val.front())
251 } -> std::same_as<void>;
252 {
253 val.push_back(typename type::value_type{})
254 } -> std::same_as<void>;
255 {
256 val.pop_back()
257 } -> std::same_as<void>;
258 {
259 val.clear()
260 } -> std::same_as<void>;
261
262 // access container
263 {
264 val.front()
265 } -> std::same_as<typename type::reference>;
266 {
267 cval.front()
268 } -> std::same_as<typename type::const_reference>;
269 {
270 val.back()
271 } -> std::same_as<typename type::reference>;
272 {
273 cval.back()
274 } -> std::same_as<typename type::const_reference>;
275 };
277
294template <typename type>
295concept random_access_container = requires (type val) {
297
298 // access container
299 {
300 val[0]
301 } -> std::same_as<typename type::reference>;
302 {
303 val.at(0)
304 } -> std::same_as<typename type::reference>;
305
306 // modify container
307 {
308 val.resize(0)
309 } -> std::same_as<void>;
310 {
311 val.resize(0, typename type::value_type{})
312 } -> std::same_as<void>;
313 };
315
330template <typename type>
331concept reservible_container = requires (type val) {
333
334 {
335 val.capacity()
336 } -> std::same_as<typename type::size_type>;
337 {
338 val.reserve(0)
339 } -> std::same_as<void>;
340 {
341 val.shrink_to_fit()
342 } -> std::same_as<void>;
343 };
345
346} // namespace seqan3
The (most general) container concept as defined by the standard library.
A more refined container concept than seqan3::sequence_container.
A more refined container concept than seqan3::random_access_container.
A more refined container concept than seqan3::container.
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
T swap(T... args)
Hide me