SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
|
CRTP base class to declare a strong typedef for a regular type to avoid ambiguous parameter settings in function calls. More...
#include <seqan3/core/detail/strong_type.hpp>
Public Types | |
using | value_type = value_t |
The underlying value type. | |
Public Member Functions | |
Constructor, destructor and assignment. | |
The standard functions are explicitly set to default. | |
constexpr | strong_type () noexcept=default |
Defaulted. | |
constexpr | strong_type (strong_type const &) noexcept=default |
Defaulted. | |
constexpr | strong_type (strong_type &&) noexcept=default |
Defaulted. | |
constexpr strong_type & | operator= (strong_type const &) noexcept=default |
Defaulted. | |
constexpr strong_type & | operator= (strong_type &&) noexcept=default |
Defaulted. | |
~strong_type () noexcept=default | |
Defaulted. | |
constexpr | strong_type (value_t _value) |
Construction from underlying value type. | |
Accessor. | |
constexpr value_t & | get () &noexcept |
Returns the underlying value. | |
constexpr value_t const & | get () const &noexcept |
Returns the underlying value. | |
constexpr value_t && | get () &&noexcept |
Returns the underlying value as rvalue. | |
constexpr value_t const && | get () const &&noexcept |
Returns the underlying value as rvalue. | |
Arithmetic additive operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr derived_t | operator+ (strong_type const &other) |
Adds addition operator to the strong type. | |
constexpr derived_t | operator- (strong_type const &other) |
Adds subtraction operator to the strong type. | |
Arithmetic multiplicative operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr derived_t | operator* (strong_type const &other) |
Adds multiplication operator to the strong type. | |
constexpr derived_t | operator/ (strong_type const &other) |
Adds division operator to the strong type. | |
constexpr derived_t | operator% (strong_type const &other) |
Adds modulo operator to the strong type. | |
Bitwise logic operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr derived_t | operator& (strong_type const &other) |
Adds bitwise and operator to the strong type. | |
constexpr derived_t | operator| (strong_type const &other) |
Adds bitwise or operator to the strong type. | |
constexpr derived_t | operator^ (strong_type const &other) |
Adds bitwise xor operator to the strong type. | |
constexpr derived_t | operator~ () |
Adds bitwise not operator to the strong type. | |
Bitwise shift operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr derived_t | operator<< (strong_type const &other) |
Adds bitwise left shift operator to the strong type. | |
template<std::integral integral_t> requires ((skills & strong_type_skill::bitwise_lshift) != strong_type_skill::none) | |
constexpr derived_t | operator<< (integral_t const shift) |
Adds bitwise left shift operator to the strong type. | |
constexpr derived_t | operator>> (strong_type const &other) |
Adds bitwise right shift operator to the strong type. | |
template<std::integral integral_t> requires ((skills & strong_type_skill::bitwise_rshift) != strong_type_skill::none) | |
constexpr derived_t | operator>> (integral_t const shift) |
Adds bitwise right shift operator to the strong type. | |
Logical operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr bool | operator&& (strong_type const &other) |
Adds logical and operator to the strong type. | |
constexpr bool | operator|| (strong_type const &other) |
Adds logical or operator to the strong type. | |
constexpr bool | operator! () |
Adds logical not operator to the strong type. | |
Increment and decrement operators. | |
Only available if the corresponding skills from seqan3::detail::strong_type_skill are added and the underlying type supports this operation. | |
constexpr derived_t & | operator++ () |
Adds pre-increment operator to the strong type. | |
constexpr derived_t | operator++ (int) |
Adds post-increment operator to the strong type. | |
constexpr derived_t & | operator-- () |
Adds pre-decrement operator to the strong type. | |
constexpr derived_t | operator-- (int) |
Adds post-decrement operator to the strong type. | |
Comparison operators | |
Only available if the corresponding skill from seqan3::detail::strong_type_skill is added. Implemented as member functions because requires does not work on friends. | |
constexpr bool | operator== (strong_type const &rhs) const |
Return whether this instance is equal to rhs . | |
constexpr bool | operator!= (strong_type const &rhs) const |
Return whether this instance is not equal to rhs . | |
Conversion operators. | |
Only available if the corresponding skill from seqan3::detail::strong_type_skill is added. | |
constexpr | operator value_t () const |
Adds explicit conversion to it's underlying type. | |
Static Public Attributes | |
static constexpr strong_type_skill | skills = skills_ |
The selected skills for this type. | |
Private Attributes | |
value_t | value |
The underlying value, which is wrapped as a strong type. | |
Related Symbols | |
(Note that these are not member symbols.) | |
Formatted output | |
template<typename char_t , derived_from_strong_type strong_type_t> | |
debug_stream_type< char_t > & | operator<< (debug_stream_type< char_t > &stream, strong_type_t &&value) |
Formatted output to a seqan3::detail::debug_stream_type. | |
CRTP base class to declare a strong typedef for a regular type to avoid ambiguous parameter settings in function calls.
value_t | The underlying type to create a strong typedef for. |
derived_t | The derived class inheriting from this base class. |
skills_ | A set of skills to be added to the expressive type. |
There are many cases in which interfaces use ambiguous parameters that can be mixed up very easily. For example, if we consider an interface that expects a window size and a number of maximal errors to search for possible hits in a region of interest, both values might be given in the form of an unsigned integer. The following snippet shows a typical interface:
The second parameter is the window size and the third parameter represents the error threshold. But what happens if the user accidentally confuses window_size
with error
? In a bigger code base, this mistake can be so subtle that it becomes hard to figure out that the search interface was used in a wrong way. Also, the compiler cannot detect this. In order to make this interface safe, we have to use a strong type. A strong type is expressive in what it actually represents as a value. In our toy example, we can define two strong types as follows:
We can now change our interface to:
Now the user is forced to pass the parameters as their named type. If the parameter order is mixed up, the compiler will emit an error message since the error
type is not convertible to the window_size
type and vice versa.
In most cases, it is sufficient to protect the user interface from misuse by using strong types. Within the implementation, the underlying value can then be extracted using the seqan3::detail::strong_type::get member functions. However, there might be scenarios where the strong type is exposed to the user to work with, but with a restricted set of operations that can be applied to the type. A familiar use case are the time typedefs of the std::chrono library. It is convenient for the user to subtract two time values representing, for example, seconds, to get the duration between two time points. But not all operations like modulo or multiplication are really useful for this. In order to add skills to the seqan3::detail::strong_type, the typedef can be further specialized with operations from the seqan3::detail::strong_type_skill enum. For example, we can further augment our error type to support increment and decrement operations:
|
related |
Formatted output to a seqan3::detail::debug_stream_type.
char_t | The char type of the seqan3::detail::debug_stream_type. |
strong_type_t | The strong type to print; must model seqan3::detail::derived_from_strong_type. |
[in,out] | stream | The output stream. |
[in] | value | The strong typed value to print. |
Prints the stored value of the given strong type.
stream_t &
A reference to the given stream.