SeqAn3 3.1.0
The Modern C++ library for sequence analysis.
strong_type.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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 <seqan3/std/concepts>
16#include <type_traits>
17
21
22namespace seqan3::detail
23{
24//------------------------------------------------------------------------------
25// enum strong_type_skill
26//------------------------------------------------------------------------------
27
33enum struct strong_type_skill
34{
35 none = 0,
36 add = 1 << 0,
37 subtract = 1 << 1,
38 multiply = 1 << 2,
39 divide = 1 << 3,
40 modulo = 1 << 4,
41 bitwise_and = 1 << 5,
42 bitwise_or = 1 << 6,
43 bitwise_xor = 1 << 7,
44 bitwise_not = 1 << 8,
45 bitwise_lshift = 1 << 9,
46 bitwise_rshift = 1 << 10,
47 logical_and = 1 << 11,
48 logical_or = 1 << 12,
49 logical_not = 1 << 13,
50 increment = 1 << 14,
51 decrement = 1 << 15,
52 convert = 1 << 16,
53 comparable = 1 << 17,
54 additive = add | subtract,
55 multiplicative = multiply | divide | modulo,
56 bitwise_logic = bitwise_and | bitwise_or | bitwise_xor | bitwise_not,
57 bitwise_shift = bitwise_lshift | bitwise_rshift,
58 logic = logical_and | logical_or | logical_not
59};
60} //namespace seqan3::detail
61
62namespace seqan3
63{
68template <>
69constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
71}
72
73namespace seqan3::detail
74{
76// forward declared for the concept
77template <typename, typename, strong_type_skill>
78class strong_type;
80
81//------------------------------------------------------------------------------
82// concept derived_from_strong_type
83//------------------------------------------------------------------------------
84
103template <typename strong_type_t>
104SEQAN3_CONCEPT derived_from_strong_type = requires (strong_type_t && obj)
105{
107
109
110 requires std::same_as<decltype(std::remove_reference_t<strong_type_t>::skills), strong_type_skill const>;
111
112 requires std::derived_from<std::remove_cvref_t<strong_type_t>,
113 strong_type<typename std::remove_reference_t<strong_type_t>::value_type,
116};
118
119//------------------------------------------------------------------------------
120// class strong_type
121//------------------------------------------------------------------------------
122
173template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
174class strong_type
175{
176public:
178 static constexpr strong_type_skill skills = skills_;
180 using value_type = value_t;
181
186 constexpr strong_type() noexcept = default;
187 constexpr strong_type(strong_type const &) noexcept = default;
188 constexpr strong_type(strong_type &&) noexcept = default;
189 constexpr strong_type & operator= (strong_type const &) noexcept = default;
190 constexpr strong_type & operator= (strong_type &&) noexcept = default;
191 ~strong_type() noexcept = default;
192
194 constexpr explicit strong_type(value_t _value) : value(std::move(_value))
195 {}
197
202 constexpr value_t & get() & noexcept
203 {
204 return value;
205 }
206
208 constexpr value_t const & get() const & noexcept
209 {
210 return value;
211 }
212
214 constexpr value_t && get() && noexcept
215 {
216 return std::move(value);
217 }
218
220 constexpr value_t const && get() const && noexcept
221 {
222 return std::move(value);
223 }
225
232 constexpr derived_t operator+(strong_type const & other)
234 requires ((skills & strong_type_skill::add) != strong_type_skill::none)
236 {
237 return derived_t{get() + other.get()};
238 }
239
241 constexpr derived_t operator-(strong_type const & other)
243 requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
245 {
246 return derived_t{get() - other.get()};
247 }
249
256 constexpr derived_t operator*(strong_type const & other)
258 requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
260 {
261 return derived_t{get() * other.get()};
262 }
263
265 constexpr derived_t operator/(strong_type const & other)
267 requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
269 {
270 return derived_t{get() / other.get()};
271 }
272
274 constexpr derived_t operator%(strong_type const & other)
276 requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
278 {
279 return derived_t{get() % other.get()};
280 }
282
290 constexpr derived_t operator&(strong_type const & other)
292 requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
294 {
295 return derived_t{get() & other.get()};
296 }
297
299 constexpr derived_t operator|(strong_type const & other)
301 requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
303 {
304 return derived_t{get() | other.get()};
305 }
306
308 constexpr derived_t operator^(strong_type const & other)
310 requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
312 {
313 return derived_t{get() ^ other.get()};
314 }
315
317 constexpr derived_t operator~()
319 requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
321 {
322 return derived_t{~get()};
323 }
325
333 constexpr derived_t operator<<(strong_type const & other)
335 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
337 {
338 return derived_t{get() << other.get()};
339 }
340
342 template <std::integral integral_t>
343 constexpr derived_t operator<<(integral_t const shift)
345 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
347 {
348 return derived_t{get() << shift};
349 }
350
352 constexpr derived_t operator>>(strong_type const & other)
354 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
356 {
357 return derived_t{get() >> other.get()};
358 }
359
361 template <std::integral integral_t>
362 constexpr derived_t operator>>(integral_t const shift)
364 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
366 {
367 return derived_t{get() >> shift};
368 }
370
378 constexpr bool operator&&(strong_type const & other)
380 requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
382 {
383 return get() && other.get();
384 }
385
387 constexpr bool operator||(strong_type const & other)
389 requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
391 {
392 return get() || other.get();
393 }
394
396 constexpr bool operator!()
398 requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
400 {
401 return !get();
402 }
404
411 constexpr derived_t & operator++()
413 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
415 {
416 ++get();
417 return static_cast<derived_t &>(*this);
418 }
419
421 constexpr derived_t operator++(int)
423 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
425 {
426 derived_t tmp{get()};
427 ++get();
428 return tmp;
429 }
430
432 constexpr derived_t & operator--()
434 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
436 {
437 --get();
438 return static_cast<derived_t &>(*this);
439 }
440
442 constexpr derived_t operator--(int)
444 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
446 {
447 derived_t tmp{get()};
448 --get();
449 return tmp;
450 }
452
462 constexpr bool operator==(strong_type const & rhs) const
464 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
466 {
467 return get() == rhs.get();
468 }
469
471 constexpr bool operator!=(strong_type const & rhs) const
473 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
475 {
476 return !(*this == rhs);
477 }
479
486 explicit constexpr operator value_t() const
488 requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
490 {
491 return get();
492 }
494
495private:
497 value_t value;
498};
499
500//------------------------------------------------------------------------------
501// related functions
502//------------------------------------------------------------------------------
503
522template <typename char_t, derived_from_strong_type strong_type_t>
523debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, strong_type_t && value)
524{
525 stream << value.get();
526 return stream;
527}
529
530} // namespace seqan3::detail
Provides seqan3::add_enum_bitwise_operators.
Provides various type traits on generic types.
The <concepts> header from C++20's standard library.
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:101
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1120
@ none
No flag is set.
Definition: debug_stream_type.hpp:32
constexpr auto convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition: convert.hpp:69
The main SeqAn3 namespace.
Definition: cigar_operation_table.hpp:2
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:429
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)