feat:data slove and update heatmap
This commit is contained in:
@@ -1,162 +1,162 @@
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
// 少量样板代码的生成宏是可以接受的,
|
||||
// 等 concept 可以作为参数的那一天,这个宏就可以废弃了
|
||||
#define CREEPER_DEFINE_CHECKER(TRAIT) \
|
||||
struct checker final { \
|
||||
template <class T> \
|
||||
static constexpr bool result = TRAIT<T>; \
|
||||
};
|
||||
|
||||
namespace creeper {
|
||||
|
||||
/// CHECKER
|
||||
template <class T>
|
||||
concept checker_trait = requires {
|
||||
{ T::template result<void> };
|
||||
};
|
||||
|
||||
template <checker_trait... Ts>
|
||||
struct CheckerOr {
|
||||
template <class T>
|
||||
static constexpr bool result = (Ts::template result<T> || ...);
|
||||
};
|
||||
template <checker_trait... Ts>
|
||||
struct CheckerAnd {
|
||||
template <class T>
|
||||
static constexpr bool result = (Ts::template result<T> && ...);
|
||||
};
|
||||
|
||||
/// PROP
|
||||
template <class Token, typename T, auto interface>
|
||||
struct SetterProp : Token {
|
||||
T value;
|
||||
|
||||
constexpr explicit SetterProp(T value) noexcept
|
||||
: value { std::move(value) } { }
|
||||
|
||||
constexpr explicit operator T(this auto&& self) noexcept { return self.value; }
|
||||
|
||||
template <typename O>
|
||||
auto operator=(O&& other) noexcept -> SetterProp&
|
||||
requires std::assignable_from<T&, O>
|
||||
{
|
||||
value = std::forward<O>(other);
|
||||
return *this; // x= y =6
|
||||
}
|
||||
|
||||
auto apply(auto& self) const noexcept -> void
|
||||
requires requires { interface(self, std::declval<T>()); }
|
||||
{
|
||||
interface(self, value);
|
||||
}
|
||||
};
|
||||
template <class Token, typename T, auto interface>
|
||||
struct DerivedProp : T, Token {
|
||||
using T::T;
|
||||
|
||||
template <typename... Args>
|
||||
requires std::constructible_from<T, Args&&...>
|
||||
constexpr explicit DerivedProp(Args&&... args)
|
||||
: T(std::forward<Args>(args)...) { }
|
||||
|
||||
template <typename U>
|
||||
requires requires(T& t, U&& u) { t = std::forward<U>(u); }
|
||||
auto operator=(U&& value) -> DerivedProp& {
|
||||
T::operator=(std::forward<U>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto apply(this auto const& self, auto& widget) noexcept -> void {
|
||||
interface(widget, static_cast<const T&>(self));
|
||||
}
|
||||
};
|
||||
template <class Token, auto interface>
|
||||
struct ActionProp : Token {
|
||||
auto apply(auto& self) const noexcept -> void
|
||||
requires requires { interface(self); }
|
||||
{
|
||||
interface(self);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief
|
||||
/// 声明式包装,非侵入式实现 Setter 的声明式化
|
||||
///
|
||||
/// 该包装器支持将 std::tuple 与单个 prop 混合传入,不受顺序限制。内部通过
|
||||
/// helper 检查 tuple 中的所有元素,递归调用 apply 将属性应用到 底层 Widget。
|
||||
/// 利用 CheckerT 延迟模板实例化,在 concept 层面约束属性类型, 从而避免因
|
||||
/// 递归参数展开而产生的海量且难以定位的模板错误。
|
||||
///
|
||||
/// @tparam W
|
||||
/// 需要被包装的组件类型。
|
||||
///
|
||||
/// @tparam checker
|
||||
/// 用于延迟模板实例化的“检查器”类型模板。典型形式如下:
|
||||
/// struct checker final {
|
||||
/// template <class T> struct result {
|
||||
/// static constexpr auto v = concept<T>;
|
||||
/// };
|
||||
/// };
|
||||
///
|
||||
/// @note
|
||||
/// 在不符合 checker 要求的类型被传入时,会在 concept 约束阶段直接报错,
|
||||
/// 提供简洁且精准的编译期错误提示,避免编译器自动展开大量构造函数
|
||||
/// 导致的冗长错误栈,但编译期报错信息依旧不友好。
|
||||
///
|
||||
template <class W, checker_trait checker>
|
||||
struct Declarative : public W {
|
||||
private:
|
||||
// For helpe check single props
|
||||
// 这里没法子塞一个 static_assert,无论如何这里都会被尝试错误地实例化
|
||||
template <typename T, class checker_>
|
||||
static constexpr auto impl_props_trait = checker_::template result<std::remove_cvref_t<T>>;
|
||||
|
||||
// For help check tuple of props
|
||||
// 使用 SFINAE 真是抱歉,没找到方便处理 tuple 的方法真是不好意思呢
|
||||
template <typename T, class checker_>
|
||||
static constexpr auto impl_tuple_trait = false;
|
||||
|
||||
template <typename... Ts, class checker_>
|
||||
static constexpr auto impl_tuple_trait<std::tuple<Ts...>, checker_> =
|
||||
(impl_props_trait<Ts, checker_> && ...);
|
||||
|
||||
public:
|
||||
/* Export widget type */
|
||||
using Widget = W;
|
||||
|
||||
/* Export checker type */
|
||||
using Checker = checker;
|
||||
|
||||
/* For check props */
|
||||
template <class T>
|
||||
static constexpr auto props_trait = impl_props_trait<std::remove_cvref_t<T>, checker>;
|
||||
|
||||
/* For check tuple */
|
||||
template <class T>
|
||||
static constexpr auto tuple_trait = impl_tuple_trait<std::remove_cvref_t<T>, checker>;
|
||||
|
||||
public:
|
||||
// 铁血的,热血的,冷血的声明式构造接口
|
||||
explicit Declarative(auto&&... props) noexcept
|
||||
requires((props_trait<decltype(props)> || tuple_trait<decltype(props)>) && ...)
|
||||
: W {} {
|
||||
(apply(std::forward<decltype(props)>(props)), ...);
|
||||
}
|
||||
auto apply(auto&& tuple) noexcept -> void
|
||||
requires tuple_trait<decltype(tuple)>
|
||||
{
|
||||
std::apply([this](auto&&... args) { (apply(std::forward<decltype(args)>(args)), ...); },
|
||||
std::forward<decltype(tuple)>(tuple));
|
||||
}
|
||||
auto apply(auto&& prop) noexcept -> void
|
||||
requires props_trait<decltype(prop)>
|
||||
{
|
||||
std::forward<decltype(prop)>(prop).apply(*this);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
// 少量样板代码的生成宏是可以接受的,
|
||||
// 等 concept 可以作为参数的那一天,这个宏就可以废弃了
|
||||
#define CREEPER_DEFINE_CHECKER(TRAIT) \
|
||||
struct checker final { \
|
||||
template <class T> \
|
||||
static constexpr bool result = TRAIT<T>; \
|
||||
};
|
||||
|
||||
namespace creeper {
|
||||
|
||||
/// CHECKER
|
||||
template <class T>
|
||||
concept checker_trait = requires {
|
||||
{ T::template result<void> };
|
||||
};
|
||||
|
||||
template <checker_trait... Ts>
|
||||
struct CheckerOr {
|
||||
template <class T>
|
||||
static constexpr bool result = (Ts::template result<T> || ...);
|
||||
};
|
||||
template <checker_trait... Ts>
|
||||
struct CheckerAnd {
|
||||
template <class T>
|
||||
static constexpr bool result = (Ts::template result<T> && ...);
|
||||
};
|
||||
|
||||
/// PROP
|
||||
template <class Token, typename T, auto interface>
|
||||
struct SetterProp : Token {
|
||||
T value;
|
||||
|
||||
constexpr explicit SetterProp(T value) noexcept
|
||||
: value { std::move(value) } { }
|
||||
|
||||
constexpr explicit operator T(this auto&& self) noexcept { return self.value; }
|
||||
|
||||
template <typename O>
|
||||
auto operator=(O&& other) noexcept -> SetterProp&
|
||||
requires std::assignable_from<T&, O>
|
||||
{
|
||||
value = std::forward<O>(other);
|
||||
return *this; // x= y =6
|
||||
}
|
||||
|
||||
auto apply(auto& self) const noexcept -> void
|
||||
requires requires { interface(self, std::declval<T>()); }
|
||||
{
|
||||
interface(self, value);
|
||||
}
|
||||
};
|
||||
template <class Token, typename T, auto interface>
|
||||
struct DerivedProp : T, Token {
|
||||
using T::T;
|
||||
|
||||
template <typename... Args>
|
||||
requires std::constructible_from<T, Args&&...>
|
||||
constexpr explicit DerivedProp(Args&&... args)
|
||||
: T(std::forward<Args>(args)...) { }
|
||||
|
||||
template <typename U>
|
||||
requires requires(T& t, U&& u) { t = std::forward<U>(u); }
|
||||
auto operator=(U&& value) -> DerivedProp& {
|
||||
T::operator=(std::forward<U>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto apply(this auto const& self, auto& widget) noexcept -> void {
|
||||
interface(widget, static_cast<const T&>(self));
|
||||
}
|
||||
};
|
||||
template <class Token, auto interface>
|
||||
struct ActionProp : Token {
|
||||
auto apply(auto& self) const noexcept -> void
|
||||
requires requires { interface(self); }
|
||||
{
|
||||
interface(self);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief
|
||||
/// 声明式包装,非侵入式实现 Setter 的声明式化
|
||||
///
|
||||
/// 该包装器支持将 std::tuple 与单个 prop 混合传入,不受顺序限制。内部通过
|
||||
/// helper 检查 tuple 中的所有元素,递归调用 apply 将属性应用到 底层 Widget。
|
||||
/// 利用 CheckerT 延迟模板实例化,在 concept 层面约束属性类型, 从而避免因
|
||||
/// 递归参数展开而产生的海量且难以定位的模板错误。
|
||||
///
|
||||
/// @tparam W
|
||||
/// 需要被包装的组件类型。
|
||||
///
|
||||
/// @tparam checker
|
||||
/// 用于延迟模板实例化的“检查器”类型模板。典型形式如下:
|
||||
/// struct checker final {
|
||||
/// template <class T> struct result {
|
||||
/// static constexpr auto v = concept<T>;
|
||||
/// };
|
||||
/// };
|
||||
///
|
||||
/// @note
|
||||
/// 在不符合 checker 要求的类型被传入时,会在 concept 约束阶段直接报错,
|
||||
/// 提供简洁且精准的编译期错误提示,避免编译器自动展开大量构造函数
|
||||
/// 导致的冗长错误栈,但编译期报错信息依旧不友好。
|
||||
///
|
||||
template <class W, checker_trait checker>
|
||||
struct Declarative : public W {
|
||||
private:
|
||||
// For helpe check single props
|
||||
// 这里没法子塞一个 static_assert,无论如何这里都会被尝试错误地实例化
|
||||
template <typename T, class checker_>
|
||||
static constexpr auto impl_props_trait = checker_::template result<std::remove_cvref_t<T>>;
|
||||
|
||||
// For help check tuple of props
|
||||
// 使用 SFINAE 真是抱歉,没找到方便处理 tuple 的方法真是不好意思呢
|
||||
template <typename T, class checker_>
|
||||
static constexpr auto impl_tuple_trait = false;
|
||||
|
||||
template <typename... Ts, class checker_>
|
||||
static constexpr auto impl_tuple_trait<std::tuple<Ts...>, checker_> =
|
||||
(impl_props_trait<Ts, checker_> && ...);
|
||||
|
||||
public:
|
||||
/* Export widget type */
|
||||
using Widget = W;
|
||||
|
||||
/* Export checker type */
|
||||
using Checker = checker;
|
||||
|
||||
/* For check props */
|
||||
template <class T>
|
||||
static constexpr auto props_trait = impl_props_trait<std::remove_cvref_t<T>, checker>;
|
||||
|
||||
/* For check tuple */
|
||||
template <class T>
|
||||
static constexpr auto tuple_trait = impl_tuple_trait<std::remove_cvref_t<T>, checker>;
|
||||
|
||||
public:
|
||||
// 铁血的,热血的,冷血的声明式构造接口
|
||||
explicit Declarative(auto&&... props) noexcept
|
||||
requires((props_trait<decltype(props)> || tuple_trait<decltype(props)>) && ...)
|
||||
: W {} {
|
||||
(apply(std::forward<decltype(props)>(props)), ...);
|
||||
}
|
||||
auto apply(auto&& tuple) noexcept -> void
|
||||
requires tuple_trait<decltype(tuple)>
|
||||
{
|
||||
std::apply([this](auto&&... args) { (apply(std::forward<decltype(args)>(args)), ...); },
|
||||
std::forward<decltype(tuple)>(tuple));
|
||||
}
|
||||
auto apply(auto&& prop) noexcept -> void
|
||||
requires props_trait<decltype(prop)>
|
||||
{
|
||||
std::forward<decltype(prop)>(prop).apply(*this);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user