SeqAn3  3.0.3
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 
22 namespace seqan3::detail
23 {
24 //------------------------------------------------------------------------------
25 // enum strong_type_skill
26 //------------------------------------------------------------------------------
27 
33 enum 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 
62 namespace seqan3
63 {
67 template <>
68 constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
70 }
71 
72 namespace seqan3::detail
73 {
75 // forward declared for the concept
76 template <typename, typename, strong_type_skill>
77 class strong_type;
79 
80 //------------------------------------------------------------------------------
81 // concept derived_from_strong_type
82 //------------------------------------------------------------------------------
83 
102 template <typename strong_type_t>
103 SEQAN3_CONCEPT derived_from_strong_type = requires (strong_type_t && obj)
104 {
106 
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 
172 template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
173 class strong_type
174 {
175 public:
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)
233  requires ((skills & strong_type_skill::add) != strong_type_skill::none)
235  {
236  return derived_t{get() + other.get()};
237  }
238 
240  constexpr derived_t operator-(strong_type const & other)
242  requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
244  {
245  return derived_t{get() - other.get()};
246  }
248 
255  constexpr derived_t operator*(strong_type const & other)
257  requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
259  {
260  return derived_t{get() * other.get()};
261  }
262 
264  constexpr derived_t operator/(strong_type const & other)
266  requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
268  {
269  return derived_t{get() / other.get()};
270  }
271 
273  constexpr derived_t operator%(strong_type const & other)
275  requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
277  {
278  return derived_t{get() % other.get()};
279  }
281 
289  constexpr derived_t operator&(strong_type const & other)
291  requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
293  {
294  return derived_t{get() & other.get()};
295  }
296 
298  constexpr derived_t operator|(strong_type const & other)
300  requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
302  {
303  return derived_t{get() | other.get()};
304  }
305 
307  constexpr derived_t operator^(strong_type const & other)
309  requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
311  {
312  return derived_t{get() ^ other.get()};
313  }
314 
316  constexpr derived_t operator~()
318  requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
320  {
321  return derived_t{~get()};
322  }
324 
332  constexpr derived_t operator<<(strong_type const & other)
334  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
336  {
337  return derived_t{get() << other.get()};
338  }
339 
341  template <std::integral integral_t>
342  constexpr derived_t operator<<(integral_t const shift)
344  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
346  {
347  return derived_t{get() << shift};
348  }
349 
351  constexpr derived_t operator>>(strong_type const & other)
353  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
355  {
356  return derived_t{get() >> other.get()};
357  }
358 
360  template <std::integral integral_t>
361  constexpr derived_t operator>>(integral_t const shift)
363  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
365  {
366  return derived_t{get() >> shift};
367  }
369 
377  constexpr bool operator&&(strong_type const & other)
379  requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
381  {
382  return get() && other.get();
383  }
384 
386  constexpr bool operator||(strong_type const & other)
388  requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
390  {
391  return get() || other.get();
392  }
393 
395  constexpr bool operator!()
397  requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
399  {
400  return !get();
401  }
403 
410  constexpr derived_t & operator++()
412  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
414  {
415  ++get();
416  return static_cast<derived_t &>(*this);
417  }
418 
420  constexpr derived_t operator++(int)
422  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
424  {
425  derived_t tmp{get()};
426  ++get();
427  return tmp;
428  }
429 
431  constexpr derived_t & operator--()
433  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
435  {
436  --get();
437  return static_cast<derived_t &>(*this);
438  }
439 
441  constexpr derived_t operator--(int)
443  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
445  {
446  derived_t tmp{get()};
447  --get();
448  return tmp;
449  }
451 
461  constexpr bool operator==(strong_type const & rhs) const
463  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
465  {
466  return get() == rhs.get();
467  }
468 
470  constexpr bool operator!=(strong_type const & rhs) const
472  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
474  {
475  return !(*this == rhs);
476  }
478 
485  explicit constexpr operator value_t() const
487  requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
489  {
490  return get();
491  }
493 
494 private:
496  value_t value;
497 };
498 
499 //------------------------------------------------------------------------------
500 // related functions
501 //------------------------------------------------------------------------------
502 
521 template <typename char_t, derived_from_strong_type strong_type_t>
522 debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, strong_type_t && value)
523 {
524  stream << value.get();
525  return stream;
526 }
528 
529 } // namespace seqan3::detail
Provides seqan3::add_enum_bitwise_operators.
The Concepts 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:1103
@ 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:74
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:74
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
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)
Provides various type traits on generic types.