89 lines
3.3 KiB
C++
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;
|
|
}
|