Utility library
#include "crow/types.hpp"
namespace Crow;
#define CROW_ASSERT(expr)
#define CROW_XASSERT(expr)
Assertion macros. CROW_ASSERT()
does the same thing as the standard
assert()
macro, except that it is not suppressed by defining NDEBUG
.
CROW_XASSERT()
performs the same test, but throws an AssertionFailure
exception instead of printing a message and aborting on failure.
using std::int8_t;
using std::int16_t;
using std::int32_t;
using std::int64_t;
using std::uint8_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;
using std::ptrdiff_t;
using std::size_t;
Imported for convenience.
using Callback = std::function<void()>;
Defined for convenience.
template <std::totally_ordered T>
std::strong_ordering compare3way(const T& a, const T& b) noexcept;
Performs a 3-way comparison by calling operator<=>
if available, otherwise
operator==
and operator<
.
constexpr std::strong_ordering to_order(ArithmeticType auto t) noexcept;
Converts a number to a strong ordering value: negative numbers map to less
,
zero to equal
, and positive numbers to greater
.
(Several of these are replacements for C++20 standard concepts that are not yet supported by all compilers, and will be removed when this is fixed.)
template <typename T> concept ArithmeticType;
Satisfied by any integral or floating point type, except bool
.
template <typename T> concept BitwiseType;
Satisfied by a type that implements the bitwise operators ~ & | ^
.
template <typename T> concept NumericType;
template <typename T> concept IntegralNumericType;
template <typename T> concept NonIntegralNumericType;
NumericType
is satisfied by any type for which a specialisation of
std::numeric_limits
exists. The other concepts break this down into
integral and non-integral types.
template <typename T> concept PrimitiveScalarType;
Satisfied if T
is a primitive scalar type.
template <typename T, typename U> concept SameBasicType;
Satisfied if T
and U
are the same type apart from any CV and reference
qualifications.
template <typename T> concept ThreeWayComparable;
Satisfied if T
supports the <=>
operator.
template <typename T>
concept UniqueCloneable = std::has_virtual_destructor_v<T>
&& requires (const T& obj) {
{ obj.clone() } -> std::convertible_to<std::unique_ptr<T>>;
};
template <typename T>
concept SharedCloneable = std::has_virtual_destructor_v<T>
&& ! UniqueCloneable<T>
&& requires (const T& obj) {
{ obj.clone() } -> std::convertible_to<std::shared_ptr<T>>;
};
template <typename T>
concept Cloneable = UniqueCloneable<T> || SharedCloneable<T>;
Satisfied if T
is the root class of a cloneable hierarchy.
template <typename T> concept IteratorType;
Satisfied if T
is an iterator.
template <typename T> concept MutableIteratorType;
Satisfied if T
is a mutable iterator.
template <typename T> concept RangeType;
template <typename T> concept MutableRangeType;
Satisfied if T
is a range, defined as having begin(T)
and end(T)
functions that can be found either by ADL or in namespace std
.
template <typename T> concept MaplikeRangeType;
template <typename T> concept MutableMaplikeRangeType;
Satisfied if T
is a range, and its value type has first
and second
data
members. The MutableMaplikeRangeType
concept only requires the second
member to be mutable.
template <typename T> concept InputIteratorType;
template <typename T> concept MutableInputIteratorType;
template <typename T> concept InputRangeType;
template <typename T> concept MutableInputRangeType;
template <typename T> concept OutputIteratorType;
template <typename T> concept MutableOutputIteratorType;
template <typename T> concept OutputRangeType;
template <typename T> concept MutableOutputRangeType;
template <typename T> concept ForwardIteratorType;
template <typename T> concept MutableForwardIteratorType;
template <typename T> concept ForwardRangeType;
template <typename T> concept MutableForwardRangeType;
template <typename T> concept BidirectionalIteratorType;
template <typename T> concept MutableBidirectionalIteratorType;
template <typename T> concept BidirectionalRangeType;
template <typename T> concept MutableBidirectionalRangeType;
template <typename T> concept RandomAccessIteratorType;
template <typename T> concept MutableRandomAccessIteratorType;
template <typename T> concept RandomAccessRangeType;
template <typename T> concept MutableRandomAccessRangeType;
These indicate whether an iterator type, or the iterator type of a range, meets the requirements for one of the standard iterator concepts. Each of these will be satisfied if the iterator’s category is at least equal to the named category.
template <typename T> concept SimpleContainerType;
template <typename T> concept AssociativeContainerType;
template <typename T> concept ContiguousContainerType;
Simplified container concepts. These do not attempt to match all the formal
requirements of the standard container concepts. SimpleContainerType
checks
for:
T::value_type, T::iterator, T::const_iterator
t.empty(), t.size()
t.begin(), t.end()
t.clear()
t.insert(it, value)
t.erase(it)
(Note that SimpleContainerType
does not match std::array
or
std::forward_list
.)
AssociativeContainerType
is a refinement of SimpleContainerType
that also
checks for:
T::key_type, T::mapped_type
value.first, value.second
t[key]
t.contains(key), t.count(key), t.erase(key), t.find(key)
ContiguousContainerType
matches SimpleContainerType
and
std::ranges::contiguous_range
.
constexpr size_t npos = std::string::npos;
Imported for convenience.
class AssertionFailure: public std::runtime_error {
AssertionFailure(std::string_view expression, std::string_view function,
std::string_view file, int line);
std::string expression() const;
std::string function() const;
std::string file() const;
int line() const noexcept;
};
The exception thrown when a CROW_XASSERT()
fails.
template <typename T = void, typename U = T> struct Plus; // +
template <typename T = void, typename U = T> struct Minus; // -
template <typename T = void, typename U = T> struct Multiplies; // *
template <typename T = void, typename U = T> struct Divides; // /
template <typename T = void, typename U = T> struct Modulus; // %
template <typename T = void, typename U = T> struct BitAnd; // &
template <typename T = void, typename U = T> struct BitOr; // |
template <typename T = void, typename U = T> struct BitXor; // ^
Heterogeneous versions of the standard function objects for binary arithmetic
operations. Like those, these have void
specializations with a templated
function call operator.
namespace Literals {
template <char... CS> constexpr int8_t operator""_s8() noexcept;
template <char... CS> constexpr int16_t operator""_s16() noexcept;
template <char... CS> constexpr int32_t operator""_s32() noexcept;
template <char... CS> constexpr int64_t operator""_s64() noexcept;
template <char... CS> constexpr uint8_t operator""_u8() noexcept;
template <char... CS> constexpr uint16_t operator""_u16() noexcept;
template <char... CS> constexpr uint32_t operator""_u32() noexcept;
template <char... CS> constexpr uint64_t operator""_u64() noexcept;
template <char... CS> constexpr ptrdiff_t operator""_z() noexcept;
template <char... CS> constexpr size_t operator""_uz() noexcept;
}
Integer literals. The standard 0b
and 0x
prefixes are understood, and
apostrophe delimiters are allowed.
struct FreeMem {
void operator()(void* ptr) const noexcept;
};
A deleter (suitable for use with smart pointers) that calls std::free()
.
template <typename T> using RangeIterator = [iterator type];
template <typename T> using RangeValue = [value type];
The iterator and value types of a range, or void
if T
is not a range.
template <typename T, bool B> struct SfinaeTrue {};
template <typename T> struct SfinaeTrue<T, true>: std::true_type {};
Creates an artificial dependency to allow enable_if
to be used in contexts
that are not directly dependent.
template <typename T> constexpr bool dependent_false = false;
Allows compile time failure in an if constexpr
branch.
template <typename T, typename U, Cloneable V = U>
requires (std::derived_from<U, V>)
class BasicClone:
public U {
[smart pointer type] clone() const override;
};
Deriving a class T
from BasicClone<T,U[,V]>
implicitly derives T
from
U
and defines the T::clone()
function (which calls the copy constructor).
The third template argument is used when a multilevel hierarchy is desired,
and the immediate base class U
is not the same as the root class V
.