16 #include <type_traits>
22 namespace seqan3::detail
31 enum struct strong_type_skill
43 bitwise_lshift = 1 << 9,
44 bitwise_rshift = 1 << 10,
45 logical_and = 1 << 11,
47 logical_not = 1 << 13,
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
64 constexpr
bool add_enum_bitwise_operators<seqan3::detail::strong_type_skill> =
true;
68 namespace seqan3::detail
72 template <
typename,
typename, strong_type_skill>
94 template <
typename strong_type_t>
96 SEQAN3_CONCEPT strong_type_specialisation = requires (strong_type_t && obj)
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,
176 template <
typename value_t,
typename derived_t, strong_type_skill skills_ = strong_type_skill::none>
181 static constexpr strong_type_skill skills = skills_;
183 using value_type = value_t;
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;
197 constexpr explicit strong_type(value_t _value) : value(
std::
move(_value))
204 constexpr value_t &
get() & noexcept
211 constexpr value_t
const &
get() const & noexcept
217 constexpr value_t &&
get() && noexcept
223 constexpr value_t
const &&
get() const && noexcept
234 constexpr derived_t operator+(strong_type
const & other)
237 requires ((skills & strong_type_skill::add) != strong_type_skill::none)
240 return derived_t{
get() + other.get()};
244 constexpr derived_t operator-(strong_type
const & other)
246 requires ((skills & strong_type_skill::subtract) != strong_type_skill::none)
249 return derived_t{
get() - other.get()};
258 constexpr derived_t operator*(strong_type
const & other)
261 requires ((skills & strong_type_skill::multiply) != strong_type_skill::none)
264 return derived_t{
get() * other.get()};
268 constexpr derived_t operator/(strong_type
const & other)
270 requires ((skills & strong_type_skill::divide) != strong_type_skill::none)
273 return derived_t{
get() / other.get()};
277 constexpr derived_t operator%(strong_type
const & other)
279 requires ((skills & strong_type_skill::modulo) != strong_type_skill::none)
282 return derived_t{
get() % other.get()};
292 constexpr derived_t operator&(strong_type
const & other)
295 requires ((skills & strong_type_skill::bitwise_and) != strong_type_skill::none)
298 return derived_t{
get() & other.get()};
302 constexpr derived_t
operator|(strong_type
const & other)
304 requires ((skills & strong_type_skill::bitwise_or) != strong_type_skill::none)
307 return derived_t{
get() | other.get()};
311 constexpr derived_t operator^(strong_type
const & other)
313 requires ((skills & strong_type_skill::bitwise_xor) != strong_type_skill::none)
316 return derived_t{
get() ^ other.get()};
320 constexpr derived_t operator~()
322 requires ((skills & strong_type_skill::bitwise_not) != strong_type_skill::
none)
325 return derived_t{~
get()};
335 constexpr derived_t
operator<<(strong_type
const & other)
338 requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none)
341 return derived_t{
get() << other.get()};
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)
351 return derived_t{
get() << shift};
355 constexpr derived_t operator>>(strong_type
const & other)
357 requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none)
360 return derived_t{
get() >> other.get()};
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)
370 return derived_t{
get() >> shift};
380 constexpr
bool operator&&(strong_type
const & other)
383 requires ((skills & strong_type_skill::logical_and) != strong_type_skill::none)
386 return get() && other.get();
390 constexpr
bool operator||(strong_type
const & other)
392 requires ((skills & strong_type_skill::logical_or) != strong_type_skill::none)
395 return get() || other.get();
399 constexpr
bool operator!()
401 requires ((skills & strong_type_skill::logical_not) != strong_type_skill::
none)
413 constexpr derived_t & operator++()
416 requires ((skills & strong_type_skill::increment) != strong_type_skill::
none)
420 return static_cast<derived_t &
>(*this);
424 constexpr derived_t operator++(
int)
426 requires ((skills & strong_type_skill::increment) != strong_type_skill::none)
429 derived_t tmp{
get()};
435 constexpr derived_t & operator--()
437 requires ((skills & strong_type_skill::decrement) != strong_type_skill::
none)
441 return static_cast<derived_t &
>(*this);
445 constexpr derived_t operator--(
int)
447 requires ((skills & strong_type_skill::decrement) != strong_type_skill::none)
450 derived_t tmp{
get()};
464 constexpr
bool operator==(strong_type
const & rhs)
const
467 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
470 return get() == rhs.get();
474 constexpr
bool operator!=(strong_type
const & rhs)
const
476 requires ((skills & strong_type_skill::comparable) != strong_type_skill::none)
479 return !(*
this == rhs);
488 explicit constexpr
operator value_t() const
491 requires ((skills & strong_type_skill::
convert) != strong_type_skill::
none)
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)
528 stream << value.get();