SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
strong_type.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 <type_traits>
14
18
19namespace seqan3::detail
20{
21//------------------------------------------------------------------------------
22// enum strong_type_skill
23//------------------------------------------------------------------------------
24
30enum struct strong_type_skill
31{
32 none = 0,
33 add = 1 << 0,
34 subtract = 1 << 1,
35 multiply = 1 << 2,
36 divide = 1 << 3,
37 modulo = 1 << 4,
38 bitwise_and = 1 << 5,
39 bitwise_or = 1 << 6,
40 bitwise_xor = 1 << 7,
41 bitwise_not = 1 << 8,
42 bitwise_lshift = 1 << 9,
43 bitwise_rshift = 1 << 10,
44 logical_and = 1 << 11,
45 logical_or = 1 << 12,
46 logical_not = 1 << 13,
47 increment = 1 << 14,
48 decrement = 1 << 15,
49 convert = 1 << 16,
50 comparable = 1 << 17,
51 additive = add | subtract,
52 multiplicative = multiply | divide | modulo,
53 bitwise_logic = bitwise_and | bitwise_or | bitwise_xor | bitwise_not,
54 bitwise_shift = bitwise_lshift | bitwise_rshift,
55 logic = logical_and | logical_or | logical_not
56};
57} //namespace seqan3::detail
58
59namespace seqan3
60{
65template <>
66inline constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
68} // namespace seqan3
69
70namespace seqan3::detail
71{
73// forward declared for the concept
74template <typename, typename, strong_type_skill>
75class strong_type;
77
78//------------------------------------------------------------------------------
79// concept derived_from_strong_type
80//------------------------------------------------------------------------------
81
100template <typename strong_type_t>
101concept derived_from_strong_type =
102 requires (strong_type_t && obj) {
104
105 {
107 };
108
109 requires std::same_as<decltype(std::remove_reference_t<strong_type_t>::skills), strong_type_skill const>;
110
111 requires std::derived_from<std::remove_cvref_t<strong_type_t>,
112 strong_type<typename std::remove_reference_t<strong_type_t>::value_type,
115 };
117
118//------------------------------------------------------------------------------
119// class strong_type
120//------------------------------------------------------------------------------
121
172template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
173class strong_type
174{
175public:
177 static constexpr strong_type_skill skills = skills_;
179 using value_type = value_t;
180
185 constexpr strong_type() noexcept = default;
186 constexpr strong_type(strong_type const &) noexcept = default;
187 constexpr strong_type(strong_type &&) noexcept = default;
188 constexpr strong_type & operator=(strong_type const &) noexcept = default;
189 constexpr strong_type & operator=(strong_type &&) noexcept = default;
190 ~strong_type() noexcept = default;
191
193 constexpr explicit strong_type(value_t _value) : value(std::move(_value))
194 {}
196
201 constexpr value_t & get() & noexcept
202 {
203 return value;
204 }
205
207 constexpr value_t const & get() const & noexcept
208 {
209 return value;
210 }
211
213 constexpr value_t && get() && noexcept
214 {
215 return std::move(value);
216 }
217
219 constexpr value_t const && get() const && noexcept
220 {
221 return std::move(value);
222 }
224
231 constexpr derived_t operator+(strong_type const & other)
232 requires ((skills & strong_type_skill::add) != strong_type_skill::none)
233 {
234 return derived_t{get() + other.get()};
235 }
236
238 constexpr derived_t operator-(strong_type const & other)
239 requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
240 {
241 return derived_t{get() - other.get()};
242 }
244
251 constexpr derived_t operator*(strong_type const & other)
252 requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
253 {
254 return derived_t{get() * other.get()};
255 }
256
258 constexpr derived_t operator/(strong_type const & other)
259 requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
260 {
261 return derived_t{get() / other.get()};
262 }
263
265 constexpr derived_t operator%(strong_type const & other)
266 requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
267 {
268 return derived_t{get() % other.get()};
269 }
271
279 constexpr derived_t operator&(strong_type const & other)
280 requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
281 {
282 return derived_t{get() & other.get()};
283 }
284
286 constexpr derived_t operator|(strong_type const & other)
287 requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
288 {
289 return derived_t{get() | other.get()};
290 }
291
293 constexpr derived_t operator^(strong_type const & other)
294 requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
295 {
296 return derived_t{get() ^ other.get()};
297 }
298
300 constexpr derived_t operator~()
301 requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
302 {
303 return derived_t{~get()};
304 }
306
314 constexpr derived_t operator<<(strong_type const & other)
315 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
316 {
317 return derived_t{get() << other.get()};
318 }
319
321 template <std::integral integral_t>
322 constexpr derived_t operator<<(integral_t const shift)
323 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
324 {
325 return derived_t{get() << shift};
326 }
327
329 constexpr derived_t operator>>(strong_type const & other)
330 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
331 {
332 return derived_t{get() >> other.get()};
333 }
334
336 template <std::integral integral_t>
337 constexpr derived_t operator>>(integral_t const shift)
338 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
339 {
340 return derived_t{get() >> shift};
341 }
343
351 constexpr bool operator&&(strong_type const & other)
352 requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
353 {
354 return get() && other.get();
355 }
356
358 constexpr bool operator||(strong_type const & other)
359 requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
360 {
361 return get() || other.get();
362 }
363
365 constexpr bool operator!()
366 requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
367 {
368 return !get();
369 }
371
378 constexpr derived_t & operator++()
379 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
380 {
381 ++get();
382 return static_cast<derived_t &>(*this);
383 }
384
386 constexpr derived_t operator++(int)
387 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
388 {
389 derived_t tmp{get()};
390 ++get();
391 return tmp;
392 }
393
395 constexpr derived_t & operator--()
396 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
397 {
398 --get();
399 return static_cast<derived_t &>(*this);
400 }
401
403 constexpr derived_t operator--(int)
404 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
405 {
406 derived_t tmp{get()};
407 --get();
408 return tmp;
409 }
411
421 constexpr bool operator==(strong_type const & rhs) const
422 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
423 {
424 return get() == rhs.get();
425 }
426
428 constexpr bool operator!=(strong_type const & rhs) const
429 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
430 {
431 return !(*this == rhs);
432 }
434
441 explicit constexpr operator value_t() const
442 requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
443 {
444 return get();
445 }
447
448private:
450 value_t value;
451};
452
453//------------------------------------------------------------------------------
454// related functions
455//------------------------------------------------------------------------------
456
475template <typename char_t, derived_from_strong_type strong_type_t>
476debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, strong_type_t && value)
477{
478 stream << value.get();
479 return stream;
480}
482
483} // namespace seqan3::detail
Provides seqan3::add_enum_bitwise_operators.
Provides various type traits on generic types.
Provides seqan3::debug_stream and related types.
debug_stream_type< char_t > & operator<<(debug_stream_type< char_t > &stream, alignment_t &&alignment)
Stream operator for alignments, which are represented as tuples of aligned sequences.
Definition debug_stream_alignment.hpp:107
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1121
@ none
No flag is set.
Definition debug_stream_type.hpp:29
constexpr auto convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition utility/views/convert.hpp:66
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition configuration.hpp:412
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
T operator/(T... args)
Hide me