SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
strong_type.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 <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 {
68 template <>
69 constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
71 } // namespace seqan3
72 
73 namespace seqan3::detail
74 {
76 // forward declared for the concept
77 template <typename, typename, strong_type_skill>
78 class strong_type;
80 
81 //------------------------------------------------------------------------------
82 // concept derived_from_strong_type
83 //------------------------------------------------------------------------------
84 
103 template <typename strong_type_t>
104 concept derived_from_strong_type =
105  requires (strong_type_t && obj) {
107 
108  {
110  };
111 
112  requires std::same_as<decltype(std::remove_reference_t<strong_type_t>::skills), strong_type_skill const>;
113 
114  requires std::derived_from<std::remove_cvref_t<strong_type_t>,
115  strong_type<typename std::remove_reference_t<strong_type_t>::value_type,
116  std::remove_cvref_t<strong_type_t>,
118  };
120 
121 //------------------------------------------------------------------------------
122 // class strong_type
123 //------------------------------------------------------------------------------
124 
175 template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
176 class strong_type
177 {
178 public:
180  static constexpr strong_type_skill skills = skills_;
182  using value_type = value_t;
183 
188  constexpr strong_type() noexcept = default;
189  constexpr strong_type(strong_type const &) noexcept = default;
190  constexpr strong_type(strong_type &&) noexcept = default;
191  constexpr strong_type & operator=(strong_type const &) noexcept = default;
192  constexpr strong_type & operator=(strong_type &&) noexcept = default;
193  ~strong_type() noexcept = default;
194 
196  constexpr explicit strong_type(value_t _value) : value(std::move(_value))
197  {}
199 
204  constexpr value_t & get() & noexcept
205  {
206  return value;
207  }
208 
210  constexpr value_t const & get() const & noexcept
211  {
212  return value;
213  }
214 
216  constexpr value_t && get() && noexcept
217  {
218  return std::move(value);
219  }
220 
222  constexpr value_t const && get() const && noexcept
223  {
224  return std::move(value);
225  }
227 
234  constexpr derived_t operator+(strong_type const & other)
235  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)
242  requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
243  {
244  return derived_t{get() - other.get()};
245  }
247 
254  constexpr derived_t operator*(strong_type const & other)
255  requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
256  {
257  return derived_t{get() * other.get()};
258  }
259 
261  constexpr derived_t operator/(strong_type const & other)
262  requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
263  {
264  return derived_t{get() / other.get()};
265  }
266 
268  constexpr derived_t operator%(strong_type const & other)
269  requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
270  {
271  return derived_t{get() % other.get()};
272  }
274 
282  constexpr derived_t operator&(strong_type const & other)
283  requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
284  {
285  return derived_t{get() & other.get()};
286  }
287 
289  constexpr derived_t operator|(strong_type const & other)
290  requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
291  {
292  return derived_t{get() | other.get()};
293  }
294 
296  constexpr derived_t operator^(strong_type const & other)
297  requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
298  {
299  return derived_t{get() ^ other.get()};
300  }
301 
303  constexpr derived_t operator~()
304  requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
305  {
306  return derived_t{~get()};
307  }
309 
317  constexpr derived_t operator<<(strong_type const & other)
318  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
319  {
320  return derived_t{get() << other.get()};
321  }
322 
324  template <std::integral integral_t>
325  constexpr derived_t operator<<(integral_t const shift)
326  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
327  {
328  return derived_t{get() << shift};
329  }
330 
332  constexpr derived_t operator>>(strong_type const & other)
333  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
334  {
335  return derived_t{get() >> other.get()};
336  }
337 
339  template <std::integral integral_t>
340  constexpr derived_t operator>>(integral_t const shift)
341  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
342  {
343  return derived_t{get() >> shift};
344  }
346 
354  constexpr bool operator&&(strong_type const & other)
355  requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
356  {
357  return get() && other.get();
358  }
359 
361  constexpr bool operator||(strong_type const & other)
362  requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
363  {
364  return get() || other.get();
365  }
366 
368  constexpr bool operator!()
369  requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
370  {
371  return !get();
372  }
374 
381  constexpr derived_t & operator++()
382  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
383  {
384  ++get();
385  return static_cast<derived_t &>(*this);
386  }
387 
389  constexpr derived_t operator++(int)
390  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
391  {
392  derived_t tmp{get()};
393  ++get();
394  return tmp;
395  }
396 
398  constexpr derived_t & operator--()
399  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
400  {
401  --get();
402  return static_cast<derived_t &>(*this);
403  }
404 
406  constexpr derived_t operator--(int)
407  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
408  {
409  derived_t tmp{get()};
410  --get();
411  return tmp;
412  }
414 
424  constexpr bool operator==(strong_type const & rhs) const
425  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
426  {
427  return get() == rhs.get();
428  }
429 
431  constexpr bool operator!=(strong_type const & rhs) const
432  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
433  {
434  return !(*this == rhs);
435  }
437 
444  explicit constexpr operator value_t() const
445  requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
446  {
447  return get();
448  }
450 
451 private:
453  value_t value;
454 };
455 
456 //------------------------------------------------------------------------------
457 // related functions
458 //------------------------------------------------------------------------------
459 
478 template <typename char_t, derived_from_strong_type strong_type_t>
479 debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, strong_type_t && value)
480 {
481  stream << value.get();
482  return stream;
483 }
485 
486 } // 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.
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
requires std::common_with< typename std::remove_reference_t< validator1_type >::option_value_type, typename std::remove_reference_t< validator2_type >::option_value_type > auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1124
@ 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: utility/views/convert.hpp:69
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
requires detail::debug_stream_range_guard< alignment_matrix_t > &&detail::matrix< alignment_matrix_t > debug_stream_type< char_t > & operator<<(debug_stream_type< char_t > &s, alignment_matrix_t &&matrix)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: debug_matrix.hpp:496
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:415
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)