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
22namespace seqan3::detail
23{
24//------------------------------------------------------------------------------
25// enum strong_type_skill
26//------------------------------------------------------------------------------
27
33enum 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
62namespace seqan3
63{
68template <>
69constexpr bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> = true;
71} // namespace seqan3
72
73namespace seqan3::detail
74{
76// forward declared for the concept
77template <typename, typename, strong_type_skill>
78class strong_type;
80
81//------------------------------------------------------------------------------
82// concept derived_from_strong_type
83//------------------------------------------------------------------------------
84
103template <typename strong_type_t>
104concept 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,
118 };
120
121//------------------------------------------------------------------------------
122// class strong_type
123//------------------------------------------------------------------------------
124
175template <typename value_t, typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
176class strong_type
177{
178public:
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
451private:
453 value_t value;
454};
455
456//------------------------------------------------------------------------------
457// related functions
458//------------------------------------------------------------------------------
459
478template <typename char_t, derived_from_strong_type strong_type_t>
479debug_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.
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:110
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: 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:415
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
T operator/(T... args)