SeqAn3 3.4.0-rc.1 The Modern C++ library for sequence analysis.
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
4
10#pragma once
11
12#include <concepts>
13#include <type_traits>
14
16
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,
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 = requires (strong_type_t && obj) {
103
105
106 requires std::same_as<decltype(std::remove_reference_t<strong_type_t>::skills), strong_type_skill const>;
107
108 requires std::derived_from<std::remove_cvref_t<strong_type_t>,
109 strong_type<typename std::remove_reference_t<strong_type_t>::value_type,
112};
114
115//------------------------------------------------------------------------------
116// class strong_type
117//------------------------------------------------------------------------------
118
169template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
170class strong_type
171{
172public:
174 static constexpr strong_type_skill skills = skills_;
176 using value_type = value_t;
177
182 constexpr strong_type() noexcept = default;
183 constexpr strong_type(strong_type const &) noexcept = default;
184 constexpr strong_type(strong_type &&) noexcept = default;
185 constexpr strong_type & operator=(strong_type const &) noexcept = default;
186 constexpr strong_type & operator=(strong_type &&) noexcept = default;
187 ~strong_type() noexcept = default;
188
190 constexpr explicit strong_type(value_t _value) : value(std::move(_value))
191 {}
193
198 constexpr value_t & get() & noexcept
199 {
200 return value;
201 }
202
204 constexpr value_t const & get() const & noexcept
205 {
206 return value;
207 }
208
210 constexpr value_t && get() && noexcept
211 {
212 return std::move(value);
213 }
214
216 constexpr value_t const && get() const && noexcept
217 {
218 return std::move(value);
219 }
221
228 constexpr derived_t operator+(strong_type const & other)
229 requires ((skills & strong_type_skill::add) != strong_type_skill::none)
230 {
231 return derived_t{get() + other.get()};
232 }
233
235 constexpr derived_t operator-(strong_type const & other)
236 requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
237 {
238 return derived_t{get() - other.get()};
239 }
241
248 constexpr derived_t operator*(strong_type const & other)
249 requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
250 {
251 return derived_t{get() * other.get()};
252 }
253
255 constexpr derived_t operator/(strong_type const & other)
256 requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
257 {
258 return derived_t{get() / other.get()};
259 }
260
262 constexpr derived_t operator%(strong_type const & other)
263 requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
264 {
265 return derived_t{get() % other.get()};
266 }
268
276 constexpr derived_t operator&(strong_type const & other)
277 requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
278 {
279 return derived_t{get() & other.get()};
280 }
281
283 constexpr derived_t operator|(strong_type const & other)
284 requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
285 {
286 return derived_t{get() | other.get()};
287 }
288
290 constexpr derived_t operator^(strong_type const & other)
291 requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
292 {
293 return derived_t{get() ^ other.get()};
294 }
295
297 constexpr derived_t operator~()
298 requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
299 {
300 return derived_t{~get()};
301 }
303
311 constexpr derived_t operator<<(strong_type const & other)
312 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
313 {
314 return derived_t{get() << other.get()};
315 }
316
318 template <std::integral integral_t>
319 constexpr derived_t operator<<(integral_t const shift)
320 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
321 {
322 return derived_t{get() << shift};
323 }
324
326 constexpr derived_t operator>>(strong_type const & other)
327 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
328 {
329 return derived_t{get() >> other.get()};
330 }
331
333 template <std::integral integral_t>
334 constexpr derived_t operator>>(integral_t const shift)
335 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
336 {
337 return derived_t{get() >> shift};
338 }
340
348 constexpr bool operator&&(strong_type const & other)
349 requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
350 {
351 return get() && other.get();
352 }
353
355 constexpr bool operator||(strong_type const & other)
356 requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
357 {
358 return get() || other.get();
359 }
360
362 constexpr bool operator!()
363 requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
364 {
365 return !get();
366 }
368
375 constexpr derived_t & operator++()
376 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
377 {
378 ++get();
379 return static_cast<derived_t &>(*this);
380 }
381
383 constexpr derived_t operator++(int)
384 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
385 {
386 derived_t tmp{get()};
387 ++get();
388 return tmp;
389 }
390
392 constexpr derived_t & operator--()
393 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
394 {
395 --get();
396 return static_cast<derived_t &>(*this);
397 }
398
400 constexpr derived_t operator--(int)
401 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
402 {
403 derived_t tmp{get()};
404 --get();
405 return tmp;
406 }
408
418 constexpr bool operator==(strong_type const & rhs) const
419 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
420 {
421 return get() == rhs.get();
422 }
423
425 constexpr bool operator!=(strong_type const & rhs) const
426 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
427 {
428 return !(*this == rhs);
429 }
431
438 explicit constexpr operator value_t() const
439 requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
440 {
441 return get();
442 }
444
445private:
447 value_t value;
448};
449
450} // namespace seqan3::detail
451
452namespace seqan3
453{
458template <detail::derived_from_strong_type strong_type_t>
459struct strong_type_printer<strong_type_t>
460{
467 template <typename stream_t, typename arg_t>
468 constexpr void operator()(stream_t & stream, arg_t && arg) const
469 {
470 stream << arg.get();
471 }
472};
473} // namespace seqan3
Provides various type traits on generic types.
Provides seqan3::debug_stream and related types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition validators.hpp:1117
@ none
No flag is set.
Definition debug_stream_type.hpp:33
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