diff --git a/sus/iter/__private/step.h b/sus/iter/__private/step.h index c792da299..3a03febf6 100644 --- a/sus/iter/__private/step.h +++ b/sus/iter/__private/step.h @@ -21,50 +21,42 @@ namespace sus::iter::__private { -template <::sus::num::Integer T> - requires(!std::same_as) +template <::sus::num::IntegerNumeric T> constexpr T step_max() noexcept { return T::MAX; } -template <::sus::num::Integer T> - requires(!std::same_as) +template <::sus::num::IntegerNumeric T> constexpr T step_forward(T l) noexcept { // SAFETY: All `Integer` can hold `1`. return l + T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn); } -template <::sus::num::Integer T> - requires(!std::same_as) +template <::sus::num::IntegerNumeric T> constexpr T step_backward(T l) noexcept { // SAFETY: All `Integer` can hold `1`. return l - T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn); } -template <::sus::num::Integer T> - requires(!std::same_as) +template <::sus::num::IntegerNumeric T> constexpr ::sus::Option<::sus::num::usize> steps_between(const T& l, const T& r) noexcept { return r.checked_sub(l).and_then( [](T steps) { return ::sus::num::usize::try_from(steps).ok(); }); } -template <::sus::num::Integer T> - requires(std::same_as) +template <::sus::num::IntegerPointer T> constexpr T step_max() noexcept { // TODO: This is dumb, so maybe uptr::MAX should exist? // https://github.com/chromium/subspace/issues/238#issuecomment-1730736193 return T::MAX_BIT_PATTERN; } -template <::sus::num::Integer T> - requires(std::same_as) +template <::sus::num::IntegerPointer T> constexpr T step_forward(T l) noexcept { return l + usize(1u); } -template <::sus::num::Integer T> - requires(std::same_as) +template <::sus::num::IntegerPointer T> constexpr T step_backward(T l) noexcept { return l - usize(1u); } -template <::sus::num::Integer T> - requires(std::same_as) +template <::sus::num::IntegerPointer T> constexpr ::sus::Option<::sus::num::usize> steps_between(const T& l, const T& r) noexcept { return r.checked_sub(l).and_then( diff --git a/sus/num/integer_concepts.h b/sus/num/integer_concepts.h index 28b06a6e8..869e8f0d8 100644 --- a/sus/num/integer_concepts.h +++ b/sus/num/integer_concepts.h @@ -24,23 +24,64 @@ namespace sus::num { -/// Unsigned Subspace integer types (u8, u16, u32, etc). +/// Unsigned Subspace numeric integer types. All of [`Unsigned`]( +/// $sus::num::Unsigned) but excluding [`uptr`]($sus::num::uptr). +/// +/// The [`uptr`]($sus::num::uptr) type is an integer but has a different API +/// that restricts how its used compared to other integer types. This can be +/// used to exclude it when it does not fit with a use case. template -concept Unsigned = +concept UnsignedNumeric = std::same_as || std::same_as || std::same_as || - std::same_as || std::same_as || std::same_as; + std::same_as || std::same_as; + +/// Unsigned Subspace pointer integer types. This is the rest of [`Unsigned`]( +/// $sus::num::Unsigned) that is not included in [`UnsignedNumeric`]( +/// $sus::num::UnsignedNumeric), which is just [`uptr`]($sus::num::uptr). +/// +/// The [`uptr`]($sus::num::uptr) type is an integer but has a different API +/// that interacts with pointers in ways numeric integers can not. This can be +/// used to exclude numeric integers when they do not fit with a use case. +template +concept UnsignedPointer = std::same_as; + +/// Unsigned Subspace integer types: [`u8`]($sus::num::u8), +/// [`u16`]($sus::num::u16), [`u32`]($sus::num::u32), [`u64`]($sus::num::u64), +/// [`usize`]($sus::num::usize), and [`uptr`]($sus::num::uptr). +template +concept Unsigned = UnsignedNumeric || UnsignedPointer; -/// Signed Subspace integer types (i8, i16, i32, etc). +/// Signed Subspace integer types: [`i8`]($sus::num::i8), +/// [`i16`]($sus::num::i16), [`i32`]($sus::num::i32), [`i64`]($sus::num::i64), +/// and [`isize`]($sus::num::isize). template concept Signed = std::same_as || std::same_as || std::same_as || std::same_as || std::same_as; -/// Signed or unsigned Subspace integer types (i8, u16, i32, u64, etc). +/// All Subspace numeric integer types. This includes all safe integer types +/// except [`uptr`]($sus::num::uptr) which represents pointers. See +/// [`UnsignedNumeric`]($sus::num::UnsignedNumeric) and +/// [`UnsignedPointer`]($sus::num::UnsignedPointer). +template +concept IntegerNumeric = UnsignedNumeric || Signed; + +/// All Subspace pointer integer types. This includes safe integer types that +/// represent pointer values, which is just [`uptr`]($sus::num::uptr). See +/// [`UnsignedNumeric`]($sus::num::UnsignedNumeric) and +/// [`UnsignedPointer`]($sus::num::UnsignedPointer). +template +concept IntegerPointer = UnsignedPointer; + +/// Signed or unsigned Subspace integer types: [`u8`]($sus::num::u8), +/// [`u16`]($sus::num::u16), [`u32`]($sus::num::u32), [`u64`]($sus::num::u64), +/// [`usize`]($sus::num::usize), [`uptr`]($sus::num::uptr), +/// [`i8`]($sus::num::i8), [`i16`]($sus::num::i16), [`i32`]($sus::num::i32), +/// [`i64`]($sus::num::i64), and [`isize`]($sus::num::isize). template -concept Integer = Unsigned || Signed; +concept Integer = IntegerNumeric || IntegerPointer; -/// Unsigned primitive integer types (unsigned char, unsigned int, etc). +/// Unsigned primitive integer types (`unsigned char`, `unsigned int`, etc). template concept UnsignedPrimitiveInteger = std::same_as || std::same_as || @@ -53,15 +94,15 @@ concept UnsignedPrimitiveInteger = std::same_as || std::same_as || std::same_as; -/// Signed primitive integer types (char, int, long, etc). +/// Signed primitive integer types (`signed char`, `int`, `long`, etc). template concept SignedPrimitiveInteger = (!std::is_unsigned_v && std::same_as) || std::same_as || std::same_as || std::same_as || std::same_as || std::same_as; -/// Signed or unsigned primitive integer types (char, int, unsigned int, -/// unsigned long, etc). +/// Signed or unsigned primitive integer types (`char`, `int`, `unsigned int`, +/// `unsigned long`, etc). template concept PrimitiveInteger = UnsignedPrimitiveInteger || SignedPrimitiveInteger; @@ -84,20 +125,25 @@ concept SignedPrimitiveEnum = template concept PrimitiveEnum = UnsignedPrimitiveEnum || SignedPrimitiveEnum; -/// Enum class (scoped enum) types that are backed by an unsigned value. +/// Enum class +/// ([scoped enumeration](https://en.cppreference.com/w/cpp/language/enum)) +/// types that are backed by an unsigned value. template concept UnsignedPrimitiveEnumClass = !UnsignedPrimitiveEnum && std::is_enum_v && UnsignedPrimitiveInteger>; -/// Enum class (scoped enum) types that are backed by a signed value. +/// Enum class +/// ([scoped enumeration](https://en.cppreference.com/w/cpp/language/enum)) +/// types that are backed by a signed value. template concept SignedPrimitiveEnumClass = !SignedPrimitiveEnum && std::is_enum_v && SignedPrimitiveInteger>; -/// Enum class (scoped enum) types that are backed by a signed or unsigned -/// value. +/// Enum class +/// ([scoped enumeration](https://en.cppreference.com/w/cpp/language/enum)) +/// types that are backed by a signed or unsigned value. template concept PrimitiveEnumClass = UnsignedPrimitiveEnumClass || SignedPrimitiveEnumClass;