Files
Adminive/backend/include/adminive/value.hpp
T
2026-08-06 16:01:04 +08:00

89 lines
3.3 KiB
C++

#pragma once
#include <concepts>
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace adminive {
template <class T, T Minimum, T Maximum>
requires std::totally_ordered<T> && (Minimum <= Maximum)
class Range_Value {
public:
using value_type = T;
static constexpr T minimum = Minimum;
static constexpr T maximum = Maximum;
constexpr explicit Range_Value(const T& value) : value_(checked(value)) {}
constexpr Range_Value(const Range_Value&) = default;
constexpr Range_Value(Range_Value&&) noexcept(std::is_nothrow_move_constructible_v<T>) = default;
constexpr Range_Value& operator=(const Range_Value&) = default;
constexpr Range_Value& operator=(Range_Value&&) noexcept(std::is_nothrow_move_assignable_v<T>) = default;
constexpr Range_Value& operator=(const T& value) {
value_ = checked(value);
return *this;
}
constexpr const T& value() const noexcept {
return value_;
}
constexpr operator const T&() const noexcept {
return value_;
}
private:
static constexpr T checked(const T& value) {
if (value < Minimum || value > Maximum) {
throw std::out_of_range("value is outside the declared range");
}
return value;
}
T value_;
};
template <class T, class Validator>
requires std::default_initializable<Validator> && std::invocable<const Validator&, const T&>
class Validated_Value {
public:
using value_type = T;
using validator_type = Validator;
constexpr explicit Validated_Value(const T& value) : value_(checked(value)) {}
constexpr Validated_Value(const Validated_Value&) = default;
constexpr Validated_Value(Validated_Value&&) noexcept(std::is_nothrow_move_constructible_v<T>) = default;
constexpr Validated_Value& operator=(const Validated_Value&) = default;
constexpr Validated_Value& operator=(Validated_Value&&) noexcept(std::is_nothrow_move_assignable_v<T>) = default;
constexpr Validated_Value& operator=(const T& value) {
value_ = checked(value);
return *this;
}
constexpr const T& value() const noexcept {
return value_;
}
constexpr operator const T&() const noexcept {
return value_;
}
private:
static constexpr T checked(const T& value) {
Validator{}(value);
return value;
}
T value_;
};
template <class T>
struct Is_Range_Value : std::false_type {};
template <class T, T Minimum, T Maximum>
struct Is_Range_Value<Range_Value<T, Minimum, Maximum>> : std::true_type {};
template <class T>
concept Range_Value_Type = Is_Range_Value<std::remove_cvref_t<T>>::value;
template <class T>
struct Is_Validated_Value : std::false_type {};
template <class T, class Validator>
struct Is_Validated_Value<Validated_Value<T, Validator>> : std::true_type {};
template <class T>
concept Validated_Value_Type = Is_Validated_Value<std::remove_cvref_t<T>>::value;
template <class T>
struct Unwrapped_Value {
using type = std::remove_cvref_t<T>;
};
template <class T, T Minimum, T Maximum>
struct Unwrapped_Value<Range_Value<T, Minimum, Maximum>> : Unwrapped_Value<T> {};
template <class T, class Validator>
struct Unwrapped_Value<Validated_Value<T, Validator>> : Unwrapped_Value<T> {};
template <class T>
using Unwrapped_Value_Type = typename Unwrapped_Value<std::remove_cvref_t<T>>::type;
}