Core utilities
Core utility library by Ross Smith
#include "rs-core/alias.hpp"
namespace RS;
enum class AliasFlags: unsigned char {
none,
cross_compare, // Define comparison operators between T and Alias
implicit_from_alias, // Define implicit conversion from Alias to T
implicit_to_alias, // Define implicit conversion from T to Alias
};
Bitmask enumeration for flags selecting features of the Alias template. All
of the usual bitwise operators are defined.
template <typename T, typename Tag = void,
AliasFlags Flags = AliasFlags::none>
class Alias;
This template wrapper creates a “hard type alias” – a new type with the same
behaviour as T, as far as possible in C++. The new type will usually
support all the same operators as T, apart from the dereference operators,
which are used to access the underlying T value.
Most of the member functions of T can be called using the arrow operator. A
few are explicitly implemented as special cases, providing direct member
functions of Alias (for example, if T has a substr() function, we
expect Alias.substr() to return another Alias instead of the plain T
that Alias->substr() would return).
Explicit conversion operators always exist in both directions between T and
Alias<T,...>, and between different instantiations of Alias for the same
T.
The second template argument, Tag, can be used to distinguish different
instantiations with the same underlying type. This can be any type, and does
not need to be complete; only its identity is used. When aliases from
different sources may be used together and distinguishing them is necessary,
incomplete dummy types can be created to give aliases a unique identity.
The third template argument, Flags, specifies optional behaviour for the
alias:
AliasFlags::cross_compare – If this is supplied, heterogeneous comparison
operators between Alias and T will be defined. By default, only
homogeneous comparison operators are defined. This flag is only allowed if
T is comparable.AliasFlags::implicit_from_alias – If this is supplied, an implicit
conversion operator from Alias to T is defined. By default, this
conversion is explicit.AliasFlags::implicit_to_alias – If this is supplied, an implicit
conversion constructor from T to Alias is defined. By default, this
conversion is explicit.AliasFlags::point_arithmetic – If this is supplied, mixed mode arithmetic
operations are generated to make the alias type act like a point-like type
to the underlying type’s distance-like arithmetic.The implicit_from_alias and implicit_to_alias flags cannot be combined,
partly because this would be likely to lead to ambiguous overload resolution
issues, but mainly because it would largely defeat the purpose of making a
hard type alias at all.
The point_arithmetic flag cannot be combined with any of the other flags,
because, again, this would defeat the purpose of making the distance-like and
point-like types distinct. This flag can only be set if the underlying type
supports the addition and subtraction operators. If this flag is set, only
the point-like mixed-mode operators are generated; no other arithmetic
operators are generated.
using Alias::underlying_type = T;
using Alias::tag_type = Tag;
Member types.
static constexpr AliasFlags Alias::flags = Flags;
Member constants.
Alias::Alias();
Default constructor. This is only defined if T is default constructible.
Alias::Alias(const Alias& a);
Alias& Alias::operator=(const Alias& a);
Copy operations. These are only defined if T is copyable.
Alias::Alias(Alias&& a);
Alias& Alias::operator=(Alias&& a);
Move operations. These are only defined if T is movable.
[optionally explicit] Alias::Alias(const T& t);
[optionally explicit] Alias::Alias(T&& t);
Alias& Alias::operator=(const T& t);
Alias& Alias::operator=(T&& t);
Conversions from a T to an Alias<T>. Conversion constructors are always
defined, and are explicit by default; implicit conversions and assignment
operators are defined if the implicit_to_alias flag is present and T has
the necessary properties.
template <typename Tag2, AliasFlags F2>
explicit Alias::Alias(const Alias<T, Tag2, F2>& a);
template <typename Tag2, AliasFlags F2>
explicit Alias::Alias(Alias<T, Tag2, F2>&& a);
Conversion constructors between different aliases based on the same underlying
type. These are always defined if the corresponding operation on T is
defined, and are always explicit.
explicit Alias::Alias(TS&&... args);
Constructor from an arbitrary argument list. This is defined for any given
argument list if the corresponding constructor for T exists, and is always
explicit regardless of whether the underlying T constructor is explicit.
Alias::~Alias() noexcept;
Destructor.
[optionally explicit] Alias::operator T() const;
Conversion operator from an Alias<T> to a T. This conversion operator is
always defined, and is explicit by default; an implicit conversion operator
is defined if the implicit_from_alias flag is present.
[optionally explicit] Alias::operator bool() const;
Conversion operator to bool. This is defined if the corresponding conversion
is defined for T, and will have the same explicitness.
T& Alias::operator*() noexcept;
const T& Alias::operator*() const noexcept;
T* Alias::operator->() noexcept;
const T* Alias::operator->() const noexcept;
Obtain a reference to the underlying T object.
Alias Alias::operator+() const;
Alias Alias::operator-() const;
Alias Alias::operator~() const;
Alias& Alias::operator++();
Alias Alias::operator++(int);
Alias& Alias::operator--();
Alias Alias::operator--(int);
Alias& Alias::operator+=(const Alias& a);
Alias& Alias::operator-=(const Alias& a);
Alias& Alias::operator*=(const Alias& a);
Alias& Alias::operator/=(const Alias& a);
Alias& Alias::operator%=(const Alias& a);
Alias& Alias::operator&=(const Alias& a);
Alias& Alias::operator|=(const Alias& a);
Alias& Alias::operator^=(const Alias& a);
Alias& Alias::operator<<=(int i);
Alias& Alias::operator>>=(int i);
Alias operator+(const Alias& a, const Alias& b);
Alias operator-(const Alias& a, const Alias& b);
Alias operator*(const Alias& a, const Alias& b);
Alias operator/(const Alias& a, const Alias& b);
Alias operator%(const Alias& a, const Alias& b);
Alias operator&(const Alias& a, const Alias& b);
Alias operator|(const Alias& a, const Alias& b);
Alias operator^(const Alias& a, const Alias& b);
Alias operator<<(const Alias& a, int i);
Alias operator>>(const Alias& a, int i);
Arithmetic operators. Each of these is defined if the corresponding operator
is defined for T. Only homogeneous operators are defined, except for the
bitwise shift operators.
Alias& Alias::operator+=(T a);
Alias& Alias::operator-=(T a);
Alias operator+(const Alias& a, T t);
Alias operator+(T t, const Alias& a);
Alias operator-(const Alias& a, T t);
T operator-(const Alias& a, const Alias& b);
Point-like arithmetic operators. These are defined only if the
point_arithmetic flag is set.
bool operator==(const Alias& a, const Alias& b);
bool operator!=(const Alias& a, const Alias& b);
bool operator<(const Alias& a, const Alias& b);
bool operator>(const Alias& a, const Alias& b);
bool operator<=(const Alias& a, const Alias& b);
bool operator>=(const Alias& a, const Alias& b);
[comparison type] operator<=>(const Alias& a, const Alias& b);
Homogeneous comparison operators. Each of these is defined if the
corresponding operator is defined for T. The three way comparison operator
returns the same type as the corresponding operator for T.
bool operator==(const Alias& a, const T& t);
bool operator==(const T& t, const Alias& a);
bool operator!=(const Alias& a, const T& t);
bool operator!=(const T& t, const Alias& a);
bool operator<(const Alias& a, const T& t);
bool operator<(const T& t, const Alias& a);
bool operator>(const Alias& a, const T& t);
bool operator>(const T& t, const Alias& a);
bool operator<=(const Alias& a, const T& t);
bool operator<=(const T& t, const Alias& a);
bool operator>=(const Alias& a, const T& t);
bool operator>=(const T& t, const Alias& a);
[comparison type] operator<=>(const Alias& a, const T& t);
[comparison type] operator<=>(const T& t, const Alias& a);
Heterogeneous comparison operators. Each of these is defined if the
cross_compare flag is present and the corresponding operator is defined for
T.
[value type]& Alias::operator[](std::size_t i);
[see below] Alias::operator[](std::size_t i) const;
Indexing operators. Defined if the corresponding operator for T is defined.
The const version can return either a const reference or a value object,
whichever is returned by the underlying call.
[iterator] Alias::begin();
[iterator] Alias::begin() const;
[iterator or sentinel] Alias::end();
[iterator or sentinel] Alias::end() const;
Range access functions. Defined if std::ranges::begin/end(T) are defined,
and returning the same type as those functions.
bool Alias::empty() const;
std::size_t Alias::size() const;
Range property functions. Defined if std::ranges::empty/size(T) are valid.
All functions in <cmath> are defined for Alias<T> if they are defined for
T (as of C++23).
Alias Alias::substr(std::size_t pos, std::size_t len = npos) const;
Defined if T::substr() is defined and returns a T or a type convertible to
it. This returns an Alias<T> wrapped around the substring, instead of the
raw T substring that Alias->substr() would return.
struct std::formatter<Alias>;
Defined if std::formatter<T> is defined, and accepts the same formatting
flags.
struct std::hash<Alias>;
Defined if std::hash<T> is defined, and returns the same value.
namespace std::numbers;
The constants in this namespace (with the "_v" suffix) are duplicated for
Alias<T> if they are defined for T.
class std::numeric_limits<Alias>;
Defined if numeric_limits<T> is specialized, and contains the same values,
converted where necessary to Alias<T>.