SeqAn3 3.2.0
The Modern C++ library for sequence analysis.
concept.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <concepts>
16#include <initializer_list>
17#include <iterator>
18#include <type_traits>
19
21
22#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
23# include <string>
24
25namespace seqan3::detail
26{
27
31template <typename basic_string_t>
32struct is_basic_string : std::false_type
33{};
34
38template <typename value_t, typename traits_t, typename allocator_t>
39struct is_basic_string<std::basic_string<value_t, traits_t, allocator_t>> : std::true_type
40{};
41
45template <typename basic_string_t>
46constexpr bool is_basic_string_v = is_basic_string<basic_string_t>::value;
47
48} // namespace seqan3::detail
49#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
50
51namespace seqan3
52{
53
72template <typename type>
73concept container = requires (type val, type val2, type const cval, typename type::iterator it) {
74 // member types
75 typename type::value_type;
76 typename type::reference;
77 typename type::const_reference;
78 /*
79 typename type::iterator;
80 requires std::forward_iterator<typename type::iterator>;
81 // NOTE check whether iterator is const convertible
82 {it} -> std::same_as<typename type::const_iterator>;
83
84 typename type::const_iterator;
85 requires std::forward_iterator<typename type::const_iterator>;
86
87 typename type::difference_type;
88 typename type::size_type;
89 requires std::is_same_v<
90 typename type::difference_type,
91 typename std::iterator_traits<typename type::iterator>::difference_type
92 >;
93 requires std::is_same_v<
94 typename std::iterator_traits<typename type::iterator>::difference_type,
95 typename std::iterator_traits<typename type::const_iterator>::difference_type
96 >;
97*/
98 // methods and operator
99 {
100 type{}
101 } -> std::same_as<type>; // default constructor
102 {
103 type{type{}}
104 } -> std::same_as<type>; // copy/move constructor
105 {
106 val = val2
107 } -> std::same_as<type &>; // assignment
108 {
109 (&val)->~type()
110 }; // destructor
111
112 {
113 val.begin()
114 } -> std::same_as<typename type::iterator>;
115 {
116 val.end()
117 } -> std::same_as<typename type::iterator>;
118 {
119 cval.begin()
120 } -> std::same_as<typename type::const_iterator>;
121 {
122 cval.end()
123 } -> std::same_as<typename type::const_iterator>;
124 {
125 val.cbegin()
126 } -> std::same_as<typename type::const_iterator>;
127 {
128 val.cend()
129 } -> std::same_as<typename type::const_iterator>;
130
131 requires !std::equality_comparable<typename type::value_type> || std::equality_comparable<type>;
132
133 {
134 val.swap(val2)
135 } -> std::same_as<void>;
136 {
137 swap(val, val2)
138 } -> std::same_as<void>;
139 {
140 std::swap(val, val2)
141 } -> std::same_as<void>;
142
143 {
144 val.size()
145 } -> std::same_as<typename type::size_type>;
146 {
147 val.max_size()
148 } -> std::same_as<typename type::size_type>;
149 {
150 val.empty()
151 } -> std::same_as<bool>;
152 };
154
171template <typename type>
172concept sequence_container =
173 requires (type val, type val2, type const cval) {
174 requires container<type>;
175
176 // construction
177 {
178 type(typename type::size_type{}, typename type::value_type{})
179 };
180 {
181 type{val2.begin(), val2.end()}
182 }; // NOTE that this could be any input iterator:
183 {
185 };
186 {
188 } -> std::same_as<type &>;
189
190 // assignment NOTE return type is type & for std::string and void for other stl containers:
191 {
192 val.assign(val2.begin(), val2.end())
193 };
194 {
196 };
197 {
198 val.assign(typename type::size_type{}, typename type::value_type{})
199 };
200
201 // modify container
202 // TODO: how do you model this?
203 // {val.emplace(typename type::const_iterator{}, ?)} -> std::same_as<typename type::iterator>;
204#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
205 {
206 val.insert(val.begin(), val2.front())
207 } -> std::same_as<typename type::iterator>;
208 {
209 val.insert(val.begin(), typename type::value_type{})
210 } -> std::same_as<typename type::iterator>;
211
212 // std::string is missing the const_iterator versions for insert in pre-C++11 ABI
213 requires detail::is_basic_string_v<type>
214 || requires (type val, type val2)
215#else // ^^^ workaround / no workaround vvv
216 requires requires (type val, type val2)
217#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
218 {
219 {
220 val.insert(val.cbegin(), val2.front())
221 } -> std::same_as<typename type::iterator>;
222 {
223 val.insert(val.cbegin(), typename type::value_type{})
224 } -> std::same_as<typename type::iterator>;
225 {
226 val.insert(val.cbegin(), typename type::size_type{}, typename type::value_type{})
227 } -> std::same_as<typename type::iterator>;
228 {
229 val.insert(val.cbegin(), val2.begin(), val2.end())
230 } -> std::same_as<typename type::iterator>;
231 {
232 val.insert(val.cbegin(), std::initializer_list<typename type::value_type>{})
233 } -> std::same_as<typename type::iterator>;
234 };
235
236#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
237 // std::string is missing the const_iterator versions for erase in pre-C++11 ABI
238 requires detail::is_basic_string_v<type>
239 || requires (type val)
240#else // ^^^ workaround / no workaround vvv
241 requires requires (type val)
242#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
243 {
244 {
245 val.erase(val.cbegin())
246 } -> std::same_as<typename type::iterator>;
247 {
248 val.erase(val.cbegin(), val.cend())
249 } -> std::same_as<typename type::iterator>;
250 };
251
252 {
253 val.push_back(val.front())
254 } -> std::same_as<void>;
255 {
256 val.push_back(typename type::value_type{})
257 } -> std::same_as<void>;
258 {
259 val.pop_back()
260 } -> std::same_as<void>;
261 {
262 val.clear()
263 } -> std::same_as<void>;
264
265 // access container
266 {
267 val.front()
268 } -> std::same_as<typename type::reference>;
269 {
270 cval.front()
271 } -> std::same_as<typename type::const_reference>;
272 {
273 val.back()
274 } -> std::same_as<typename type::reference>;
275 {
276 cval.back()
277 } -> std::same_as<typename type::const_reference>;
278 };
280
297template <typename type>
298concept random_access_container = requires (type val) {
300
301 // access container
302 {
303 val[0]
304 } -> std::same_as<typename type::reference>;
305 {
306 val.at(0)
307 } -> std::same_as<typename type::reference>;
308
309 // modify container
310 {
311 val.resize(0)
312 } -> std::same_as<void>;
313 {
314 val.resize(0, typename type::value_type{})
315 } -> std::same_as<void>;
316 };
318
333template <typename type>
334concept reservible_container = requires (type val) {
336
337 {
338 val.capacity()
339 } -> std::same_as<typename type::size_type>;
340 {
341 val.reserve(0)
342 } -> std::same_as<void>;
343 {
344 val.shrink_to_fit()
345 } -> std::same_as<void>;
346 };
348
349} // 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:29
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
T swap(T... args)