SeqAn3  3.1.0-rc.1
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 {
68 template <>
69 constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
71 }
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 SEQAN3_CONCEPT derived_from_strong_type = requires (strong_type_t && obj)
105 {
106  typename std::remove_reference_t<strong_type_t>::value_type;
107 
108  { std::remove_reference_t<strong_type_t>::skills };
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,
115  std::remove_reference_t<strong_type_t>::skills>>;
116 };
118 
119 //------------------------------------------------------------------------------
120 // class strong_type
121 //------------------------------------------------------------------------------
122 
173 template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
174 class strong_type
175 {
176 public:
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 
495 private:
497  value_t value;
498 };
499 
500 //------------------------------------------------------------------------------
501 // related functions
502 //------------------------------------------------------------------------------
503 
522 template <typename char_t, derived_from_strong_type strong_type_t>
523 debug_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 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:1096
@ 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: 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.
Definition: affine_cell_proxy.hpp:438
typename remove_cvref< t >::type remove_cvref_t
Return the input type with const, volatile and references removed (transformation_trait shortcut).
Definition: type_traits:54
Provides C++20 additions to the type_traits header.