SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
strong_type.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, 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 
31 enum struct strong_type_skill
32 {
33  none = 0,
34  add = 1 << 0,
35  subtract = 1 << 1,
36  multiply = 1 << 2,
37  divide = 1 << 3,
38  modulo = 1 << 4,
39  bitwise_and = 1 << 5,
40  bitwise_or = 1 << 6,
41  bitwise_xor = 1 << 7,
42  bitwise_not = 1 << 8,
43  bitwise_lshift = 1 << 9,
44  bitwise_rshift = 1 << 10,
45  logical_and = 1 << 11,
46  logical_or = 1 << 12,
47  logical_not = 1 << 13,
48  increment = 1 << 14,
49  decrement = 1 << 15,
50  convert = 1 << 16,
51  comparable = 1 << 17,
52  additive = add | subtract,
53  multiplicative = multiply | divide | modulo,
54  bitwise_logic = bitwise_and | bitwise_or | bitwise_xor | bitwise_not,
55  bitwise_shift = bitwise_lshift | bitwise_rshift,
56  logic = logical_and | logical_or | logical_not
57 };
58 } //namespace seqan3::detail
59 
60 namespace seqan3
61 {
63 template <>
64 constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
66 }
67 
68 namespace seqan3::detail
69 {
71 // forward declared for the concept
72 template <typename, typename, strong_type_skill>
73 class strong_type;
75 
76 //------------------------------------------------------------------------------
77 // concept strong_type_specialisation
78 //------------------------------------------------------------------------------
79 
94 template <typename strong_type_t>
96 SEQAN3_CONCEPT strong_type_specialisation = requires (strong_type_t && obj)
97 {
99 
104 
110  requires std::same_as<decltype(std::remove_reference_t<strong_type_t>::skills), strong_type_skill const>;
112 
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,
120 };
123 
124 //------------------------------------------------------------------------------
125 // class strong_type
126 //------------------------------------------------------------------------------
127 
176 template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
177 class strong_type
178 {
179 public:
181  static constexpr strong_type_skill skills = skills_;
183  using value_type = value_t;
184 
189  constexpr strong_type() noexcept = default;
190  constexpr strong_type(strong_type const &) noexcept = default;
191  constexpr strong_type(strong_type &&) noexcept = default;
192  constexpr strong_type & operator= (strong_type const &) noexcept = default;
193  constexpr strong_type & operator= (strong_type &&) noexcept = default;
194  ~strong_type() noexcept = default;
195 
197  constexpr explicit strong_type(value_t _value) : value(std::move(_value))
198  {}
200 
204  constexpr value_t & get() & noexcept
206  {
207  return value;
208  }
209 
211  constexpr value_t const & get() const & noexcept
212  {
213  return value;
214  }
215 
217  constexpr value_t && get() && noexcept
218  {
219  return std::move(value);
220  }
221 
223  constexpr value_t const && get() const && noexcept
224  {
225  return std::move(value);
226  }
228 
234  constexpr derived_t operator+(strong_type const & other)
237  requires ((skills & strong_type_skill::add) != strong_type_skill::none)
239  {
240  return derived_t{get() + other.get()};
241  }
242 
244  constexpr derived_t operator-(strong_type const & other)
246  requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
248  {
249  return derived_t{get() - other.get()};
250  }
252 
258  constexpr derived_t operator*(strong_type const & other)
261  requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
263  {
264  return derived_t{get() * other.get()};
265  }
266 
268  constexpr derived_t operator/(strong_type const & other)
270  requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
272  {
273  return derived_t{get() / other.get()};
274  }
275 
277  constexpr derived_t operator%(strong_type const & other)
279  requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
281  {
282  return derived_t{get() % other.get()};
283  }
285 
292  constexpr derived_t operator&(strong_type const & other)
295  requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
297  {
298  return derived_t{get() & other.get()};
299  }
300 
302  constexpr derived_t operator|(strong_type const & other)
304  requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
306  {
307  return derived_t{get() | other.get()};
308  }
309 
311  constexpr derived_t operator^(strong_type const & other)
313  requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
315  {
316  return derived_t{get() ^ other.get()};
317  }
318 
320  constexpr derived_t operator~()
322  requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
324  {
325  return derived_t{~get()};
326  }
328 
335  constexpr derived_t operator<<(strong_type const & other)
338  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
340  {
341  return derived_t{get() << other.get()};
342  }
343 
345  template <std::integral integral_t>
346  constexpr derived_t operator<<(integral_t const shift)
348  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
350  {
351  return derived_t{get() << shift};
352  }
353 
355  constexpr derived_t operator>>(strong_type const & other)
357  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
359  {
360  return derived_t{get() >> other.get()};
361  }
362 
364  template <std::integral integral_t>
365  constexpr derived_t operator>>(integral_t const shift)
367  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
369  {
370  return derived_t{get() >> shift};
371  }
373 
380  constexpr bool operator&&(strong_type const & other)
383  requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
385  {
386  return get() && other.get();
387  }
388 
390  constexpr bool operator||(strong_type const & other)
392  requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
394  {
395  return get() || other.get();
396  }
397 
399  constexpr bool operator!()
401  requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
403  {
404  return !get();
405  }
407 
413  constexpr derived_t & operator++()
416  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
418  {
419  ++get();
420  return static_cast<derived_t &>(*this);
421  }
422 
424  constexpr derived_t operator++(int)
426  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
428  {
429  derived_t tmp{get()};
430  ++get();
431  return tmp;
432  }
433 
435  constexpr derived_t & operator--()
437  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
439  {
440  --get();
441  return static_cast<derived_t &>(*this);
442  }
443 
445  constexpr derived_t operator--(int)
447  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
449  {
450  derived_t tmp{get()};
451  --get();
452  return tmp;
453  }
455 
464  constexpr bool operator==(strong_type const & rhs) const
467  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
469  {
470  return get() == rhs.get();
471  }
472 
474  constexpr bool operator!=(strong_type const & rhs) const
476  requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
478  {
479  return !(*this == rhs);
480  }
482 
488  explicit constexpr operator value_t() const
491  requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
493  {
494  return get();
495  }
497 
498 private:
500  value_t value;
501 };
502 
503 //------------------------------------------------------------------------------
504 // related functions
505 //------------------------------------------------------------------------------
506 
525 template <typename char_t, strong_type_specialisation strong_type_t>
526 debug_stream_type<char_t> & operator<<(debug_stream_type<char_t> & stream, strong_type_t && value)
527 {
528  stream << value.get();
529  return stream;
530 }
532 
533 } // namespace seqan3::detail
std::rel_ops::operator!=
T operator!=(T... args)
seqan3::get
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:627
basic.hpp
Provides various type traits on generic types.
debug_stream_type.hpp
Provides seqan3::debug_stream and related types.
seqan3::operator|
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators.
Definition: validators.hpp:1037
concepts
The Concepts library.
seqan3::views::move
auto const move
A view that turns lvalue-references into rvalue-references.
Definition: move.hpp:68
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
add_enum_bitwise_operators.hpp
Provides seqan3::add_enum_bitwise_operators.
std::remove_reference_t
std
SeqAn specific customisations in the standard namespace.
seqan3::operator<<
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:103
seqan3::none
@ none
No flag is set.
Definition: debug_stream_type.hpp:30
std::remove_cvref_t
seqan3::views::convert
auto const convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition: convert.hpp:71