Merge remote-tracking branch 'upstream/templatable-value-specialize' into integration

This commit is contained in:
J. Nick Koston
2026-04-07 14:39:38 -10:00
3 changed files with 12 additions and 4 deletions
+1 -1
View File
@@ -317,7 +317,7 @@ void LvglComponent::flush_cb_(lv_display_t *disp_drv, const lv_area_t *area, uin
lv_display_flush_ready(disp_drv);
}
IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableFn<uint32_t> timeout) : timeout_(std::move(timeout)) {
IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableFn<uint32_t> timeout) : timeout_(timeout) {
parent->add_on_idle_callback([this](uint32_t idle_time) {
if (!this->is_idle_ && idle_time > this->timeout_.value()) {
this->is_idle_ = true;
+2 -2
View File
@@ -213,12 +213,12 @@ optional<float> LambdaFilter::new_value(float value) {
}
// OffsetFilter
OffsetFilter::OffsetFilter(TemplatableFn<float> offset) : offset_(std::move(offset)) {}
OffsetFilter::OffsetFilter(TemplatableFn<float> offset) : offset_(offset) {}
optional<float> OffsetFilter::new_value(float value) { return value + this->offset_.value(); }
// MultiplyFilter
MultiplyFilter::MultiplyFilter(TemplatableFn<float> multiplier) : multiplier_(std::move(multiplier)) {}
MultiplyFilter::MultiplyFilter(TemplatableFn<float> multiplier) : multiplier_(multiplier) {}
optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); }
+9 -1
View File
@@ -41,10 +41,18 @@ template<typename T, typename... X> class TemplatableFn {
public:
TemplatableFn() = default;
// Exact return type match — direct function pointer storage
template<typename F> TemplatableFn(F f) requires std::convertible_to<F, T (*)(X...)> : f_(f) {}
// Convertible return type (e.g., int -> uint8_t) — casting trampoline.
// Stateless lambdas are default-constructible in C++20, so F{} recreates the lambda inside
// the trampoline without capturing. This compiles to the same code as a direct call + cast.
// Deprecated: codegen should use the correct output type to avoid the trampoline.
template<typename F>
TemplatableFn(F) requires std::invocable<F, X...> &&(!std::convertible_to<F, T (*)(X...)>) = delete;
[[deprecated("Lambda return type does not match TemplatableFn<T> — use the correct type in "
"codegen")]] TemplatableFn(F) requires(!std::convertible_to<F, T (*)(X...)>) &&
std::invocable<F, X...> &&std::convertible_to<std::invoke_result_t<F, X...>, T> &&std::is_empty_v<F>
&&std::default_initializable<F> : f_([](X... x) -> T { return static_cast<T>(F{}(x...)); }) {}
bool has_value() const { return this->f_ != nullptr; }