SeqAn3
strong_type.hpp
Go to the documentation of this file.
1 // ============================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ============================================================================
4 //
5 // Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin
6 // Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 //
33 // ============================================================================
34 
40 #pragma once
41 
42 #include <type_traits>
43 
46 #include <seqan3/std/concepts>
47 
48 namespace seqan3::detail
49 {
50 
54 enum struct strong_type_skill
55 {
56  none = 0,
57  add = 1 << 0,
58  subtract = 1 << 1,
59  multiply = 1 << 2,
60  divide = 1 << 3,
61  modulo = 1 << 4,
62  bitwise_and = 1 << 5,
63  bitwise_or = 1 << 6,
64  bitwise_xor = 1 << 7,
65  bitwise_not = 1 << 8,
66  bitwise_lshift = 1 << 9,
67  bitwise_rshift = 1 << 10,
68  logical_and = 1 << 11,
69  logical_or = 1 << 12,
70  logical_not = 1 << 13,
71  increment = 1 << 14,
72  decrement = 1 << 15,
73  convert = 1 << 16,
74  additive = add | subtract,
75  multiplicative = multiply | divide | modulo,
76  bitwise_logic = bitwise_and | bitwise_or | bitwise_xor | bitwise_not,
77  bitwise_shift = bitwise_lshift | bitwise_rshift,
78  logic = logical_and | logical_or | logical_not
79 };
80 } //namespace seqan3::detail
81 
82 namespace seqan3
83 {
85 template <>
86 constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
88 }
89 
90 namespace seqan3::detail
91 {
92 
141 template <typename value_t, typename derived_t, strong_type_skill skills = strong_type_skill::none>
142 class strong_type
143 {
144 public:
145 
147  using value_type = value_t;
148 
153  constexpr strong_type() = default;
154  constexpr strong_type(strong_type const &) = default;
155  constexpr strong_type(strong_type &&) = default;
156  constexpr strong_type & operator= (strong_type const &) = default;
157  constexpr strong_type & operator= (strong_type &&) = default;
158  ~strong_type() = default;
159 
161  constexpr explicit strong_type(value_t _value) : value(std::move(_value))
162  {}
164 
168  constexpr value_t & get() & noexcept
170  {
171  return value;
172  }
173 
175  constexpr value_t const & get() const & noexcept
176  {
177  return value;
178  }
179 
181  constexpr value_t && get() && noexcept
182  {
183  return std::move(value);
184  }
185 
187  constexpr value_t const && get() const && noexcept
188  {
189  return std::move(value);
190  }
192 
198  constexpr derived_t operator+(strong_type const & other)
201  requires ((skills & strong_type_skill::add) != strong_type_skill::none)
203  {
204  return derived_t{get() + other.get()};
205  }
206 
208  constexpr derived_t operator-(strong_type const & other)
210  requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
212  {
213  return derived_t{get() - other.get()};
214  }
216 
222  constexpr derived_t operator*(strong_type const & other)
225  requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
227  {
228  return derived_t{get() * other.get()};
229  }
230 
232  constexpr derived_t operator/(strong_type const & other)
234  requires ((skills & strong_type_skill::divide) != 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::modulo) != strong_type_skill::none)
245  {
246  return derived_t{get() % other.get()};
247  }
249 
256  constexpr derived_t operator&(strong_type const & other)
259  requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
261  {
262  return derived_t{get() & other.get()};
263  }
264 
266  constexpr derived_t operator|(strong_type const & other)
268  requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
270  {
271  return derived_t{get() | other.get()};
272  }
273 
275  constexpr derived_t operator^(strong_type const & other)
277  requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
279  {
280  return derived_t{get() ^ other.get()};
281  }
282 
284  constexpr derived_t operator~()
286  requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::none)
288  {
289  return derived_t{~get()};
290  }
292 
299  constexpr derived_t operator<<(strong_type const & other)
302  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
304  {
305  return derived_t{get() << other.get()};
306  }
307 
309  template <std::Integral integral_t>
310  constexpr derived_t operator<<(integral_t const shift)
312  requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
314  {
315  return derived_t{get() << shift};
316  }
317 
319  constexpr derived_t operator>>(strong_type const & other)
321  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
323  {
324  return derived_t{get() >> other.get()};
325  }
326 
328  template <std::Integral integral_t>
329  constexpr derived_t operator>>(integral_t const shift)
331  requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
333  {
334  return derived_t{get() >> shift};
335  }
337 
344  constexpr bool operator&&(strong_type const & other)
347  requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
349  {
350  return get() && other.get();
351  }
352 
354  constexpr bool operator||(strong_type const & other)
356  requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
358  {
359  return get() || other.get();
360  }
361 
363  constexpr bool operator!()
365  requires ((skills & strong_type_skill::logical_not) != strong_type_skill::none)
367  {
368  return !get();
369  }
371 
377  constexpr derived_t & operator++()
380  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
382  {
383  ++get();
384  return static_cast<derived_t &>(*this);
385  }
386 
388  constexpr derived_t operator++(int)
390  requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
392  {
393  derived_t tmp{get()};
394  ++get();
395  return tmp;
396  }
397 
399  constexpr derived_t & operator--()
401  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
403  {
404  --get();
405  return static_cast<derived_t &>(*this);
406  }
407 
409  constexpr derived_t operator--(int)
411  requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
413  {
414  derived_t tmp{get()};
415  --get();
416  return tmp;
417  }
419 
425  explicit constexpr operator value_t() const
428  requires ((skills & strong_type_skill::convert) != strong_type_skill::none)
430  {
431  return get();
432  }
434 private:
436  value_t value;
437 };
438 
439 } // namespace seqan3::detail
auto const convert
A view that converts each element in the input range (implicitly or via static_cast).
Definition: convert.hpp:89
Provides seqan3::add_enum_bitwise_operators.
debug_stream_type & operator<<(debug_stream_type &stream, tuple_t const &alignment)
Streaming operator for alignments, which are represented as tuples of aligned sequences.
Definition: aligned_sequence_concept.hpp:370
SeqAn specific customisations in the standard namespace.
Definition: align_result.hpp:221
No flag is set.
Definition: debug_stream.hpp:65
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:58
constexpr auto const & get(detail::configuration< cfg_elements_t... > const &cfg) noexcept
Definition: utility.hpp:364
The Concepts library.
Definition: aligned_sequence_concept.hpp:288
Provides C++20 additions to the type_traits header.
Provides various metafunctions on generic types.
auto operator|(validator1_type &&vali1, validator2_type &&vali2)
Enables the chaining of validators. !
Definition: validators.hpp:671