The strong typedef class and helper macros.
Motivation
C++ offers typedefs to provide aliases (different names) for a type. Typedefs are useful to shorten complicated types and to make type usage consistent. However, they do not prevent accidental misuse. Consider:
void f(std::string const &first_name);
void g()
{
std::string const email_address{"a@b.com"};
f(email_address);
}
Accidents like this can be prevented by creating new types first_name and email_address that are wrappers around strings. Because both of them are distinct types, they cannot be implicitly converted into each other.
Strong typedefs are thin wrappers around types that are easy to define:
void f(first_name const &);
void g()
{
email_address const address{std::string{"a@b.com"}};
}
Parameters
Strong typedefs are especially helpful to distinguish function parameters at the type level. Consider the following function:
void f(int vertex_count, bool enable_culling, char character);
Even with parameter names in the function's declaration, the interface is easy to misuse. For example, the following code will compile (possibly without any warnings):
Instead, we introduce strong typedefs for the parameters.
void f(vertex_count, enable_culling, draw_char);
The correct function call then looks like this:
f(vertex_count(1), enable_culling(true), draw_char('c'));
Operations
The get function extracts the value of a strong typedef.
void f(first_name const &_name) { std::cout << _name.get() << '\n'; }
Strong typedef wraps almost all operators, which are found in their respective headers.
void f(distance const _d1, distance const _d2) { std::cout << (_d1 - _d2) << '\n'; }
Internals
When declaring two strong typedefs with the same underlying type, two distinct types need to be created:
static_assert(!std::is_same_v<first, second>, "Both types must be different");
To achieve that, the FCPPT_DECLARE_STRONG_TYPEDEF macro first creates an empty struct containing the name you specify as the first parameter. This is then used as the second parameter to fcppt::strong_typedef to make it a distinct type.
Header files
| Header file | Description |
strong_typedef_fwd.hpp | Contains fcppt::strong_typedef's declaration. |
strong_typedef_decl.hpp | Contains fcppt::strong_typedef's definition. |
strong_typedef_impl.hpp | Contains the definition of fcppt::strong_typedef's member functions. |
strong_typedef.hpp | Includes strong_typedef_impl.hpp, strong_typedef_operators.hpp and strong_typedef_std_hash.hpp. |
strong_typedef_operators.hpp | Includes strong_typedef_arithmetic.hpp, strong_typedef_assignment.hpp, strong_typedef_bitwise.hpp and strong_typedef_comparison.hpp. |
strong_typedef_input.hpp | Contains operator>>. |
strong_typedef_output.hpp | Contains operator<<. |
declare_strong_typedef.hpp | Contains FCPPT_DECLARE_STRONG_TYPEDEF. |
|
| template<typename Tag, typename Type> |
| fcppt::strong_typedef< std::remove_cvref_t< Type >, Tag > | fcppt::make_strong_typedef (Type &&_value) |
| | Creates a new strong typedef given a tag and a value.
|
| template<typename StrongTypedef1, typename Function, typename... StrongTypedefs> |
| auto | fcppt::strong_typedef_apply (Function const &_function, StrongTypedef1 &&_strong_typedef1, StrongTypedefs &&..._strong_typedefs) -> fcppt::strong_typedef< decltype(_function(fcppt::move_if_rvalue< StrongTypedef1 >(_strong_typedef1.get()), fcppt::move_if_rvalue< StrongTypedefs >(_strong_typedefs.get())...)), fcppt::strong_typedef_tag< std::remove_cvref_t< StrongTypedef1 > > > |
| | Applies a function to multiple strong typedefs.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator+ (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Add two strong typedefs.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator- (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Subtract two strong typedefs.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator* (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Multiply two strong typedefs.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator- (fcppt::strong_typedef< T, Tag > const &_value) |
| | Unary minus.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator++ (fcppt::strong_typedef< T, Tag > &_value) |
| | Preincrement operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator-- (fcppt::strong_typedef< T, Tag > &_value) |
| | Predecrement operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator++ (fcppt::strong_typedef< T, Tag > &_value, int) |
| | Postincrement operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator-- (fcppt::strong_typedef< T, Tag > &_value, int) |
| | Postdecrement operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator+= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Add and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator-= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Subtract and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator*= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Multiply and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator&= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise and and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator|= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise or and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > & | fcppt::operator^= (fcppt::strong_typedef< T, Tag > &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise xor and assign operator.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator& (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise and.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator| (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise or.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator^ (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Bitwise xor.
|
| template<typename T, typename Tag> |
| fcppt::strong_typedef< T, Tag > | fcppt::operator~ (fcppt::strong_typedef< T, Tag > const &_value) |
| | Bitwise negation.
|
| template<typename T, typename Tag> |
| bool | fcppt::operator< (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator less.
|
| template<typename T, typename Tag> |
| bool | fcppt::operator<= (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator less equal.
|
| template<typename T, typename Tag> |
| bool | fcppt::operator> (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator greater.
|
| template<typename T, typename Tag> |
| bool | fcppt::operator>= (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator greater equal.
|
template<typename T, typename Tag>
requires std::equality_comparable<T> |
| bool | fcppt::operator== (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator equal.
|
template<typename T, typename Tag>
requires std::equality_comparable<T> |
| bool | fcppt::operator!= (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Operator not equal.
|
template<typename T, typename Tag>
requires std::three_way_comparable<T> |
| auto | fcppt::operator<=> (fcppt::strong_typedef< T, Tag > const &_left, fcppt::strong_typedef< T, Tag > const &_right) |
| | Three-way comparison.
|
template<typename StrongTypedef, typename Conv, typename Arg>
requires fcppt::is_strong_typedef<StrongTypedef>::value |
| constexpr StrongTypedef | fcppt::strong_typedef_construct_cast (Arg const &_arg) |
| | Applies a cast from fcppt.cast and then construct the strong typedef.
|
| template<typename Ch, typename Traits, typename T, typename Tag> |
| std::basic_istream< Ch, Traits > & | fcppt::operator>> (std::basic_istream< Ch, Traits > &_stream, fcppt::strong_typedef< T, Tag > &_value) |
| | Input operator for strong typedefs.
|
| template<typename StrongTypedef, typename Function> |
| auto | fcppt::strong_typedef_map (StrongTypedef &&_input, Function const &_function) -> fcppt::strong_typedef< decltype(_function(fcppt::move_if_rvalue< StrongTypedef >(_input.get()))), fcppt::strong_typedef_tag< std::remove_cvref_t< StrongTypedef > > > |
| | Maps over a strong typedef.
|
| template<typename Ch, typename Traits, typename T, typename Tag> |
| std::basic_ostream< Ch, Traits > & | fcppt::operator<< (std::basic_ostream< Ch, Traits > &_stream, fcppt::strong_typedef< T, Tag > const &_value) |
| | Output operator for strong typedefs.
|