mirror of
https://github.com/esphome/esphome.git
synced 2025-10-31 23:21:54 +00:00
Merge branch 'template_value_func_pointers' into integration
This commit is contained in:
@@ -16,12 +16,7 @@ from esphome.const import (
|
|||||||
CONF_UPDATE_INTERVAL,
|
CONF_UPDATE_INTERVAL,
|
||||||
)
|
)
|
||||||
from esphome.core import ID
|
from esphome.core import ID
|
||||||
from esphome.cpp_generator import (
|
from esphome.cpp_generator import MockObj, MockObjClass, TemplateArgsType
|
||||||
LambdaExpression,
|
|
||||||
MockObj,
|
|
||||||
MockObjClass,
|
|
||||||
TemplateArgsType,
|
|
||||||
)
|
|
||||||
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
|
||||||
from esphome.types import ConfigType
|
from esphome.types import ConfigType
|
||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
@@ -92,7 +87,6 @@ def validate_potentially_or_condition(value):
|
|||||||
|
|
||||||
DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component)
|
DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component)
|
||||||
LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
|
LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
|
||||||
StatelessLambdaAction = cg.esphome_ns.class_("StatelessLambdaAction", Action)
|
|
||||||
IfAction = cg.esphome_ns.class_("IfAction", Action)
|
IfAction = cg.esphome_ns.class_("IfAction", Action)
|
||||||
WhileAction = cg.esphome_ns.class_("WhileAction", Action)
|
WhileAction = cg.esphome_ns.class_("WhileAction", Action)
|
||||||
RepeatAction = cg.esphome_ns.class_("RepeatAction", Action)
|
RepeatAction = cg.esphome_ns.class_("RepeatAction", Action)
|
||||||
@@ -103,40 +97,9 @@ ResumeComponentAction = cg.esphome_ns.class_("ResumeComponentAction", Action)
|
|||||||
Automation = cg.esphome_ns.class_("Automation")
|
Automation = cg.esphome_ns.class_("Automation")
|
||||||
|
|
||||||
LambdaCondition = cg.esphome_ns.class_("LambdaCondition", Condition)
|
LambdaCondition = cg.esphome_ns.class_("LambdaCondition", Condition)
|
||||||
StatelessLambdaCondition = cg.esphome_ns.class_("StatelessLambdaCondition", Condition)
|
|
||||||
ForCondition = cg.esphome_ns.class_("ForCondition", Condition, cg.Component)
|
ForCondition = cg.esphome_ns.class_("ForCondition", Condition, cg.Component)
|
||||||
|
|
||||||
|
|
||||||
def new_lambda_pvariable(
|
|
||||||
id_obj: ID,
|
|
||||||
lambda_expr: LambdaExpression,
|
|
||||||
stateless_class: MockObjClass,
|
|
||||||
template_arg: cg.TemplateArguments | None = None,
|
|
||||||
) -> MockObj:
|
|
||||||
"""Create Pvariable for lambda, using stateless class if applicable.
|
|
||||||
|
|
||||||
Combines ID selection and Pvariable creation in one call. For stateless
|
|
||||||
lambdas (empty capture), uses function pointer instead of std::function.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
id_obj: The ID object (action_id, condition_id, or filter_id)
|
|
||||||
lambda_expr: The lambda expression object
|
|
||||||
stateless_class: The stateless class to use for stateless lambdas
|
|
||||||
template_arg: Optional template arguments (for actions/conditions)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The created Pvariable
|
|
||||||
"""
|
|
||||||
# For stateless lambdas, use function pointer instead of std::function
|
|
||||||
if lambda_expr.capture == "":
|
|
||||||
id_obj = id_obj.copy()
|
|
||||||
id_obj.type = stateless_class
|
|
||||||
|
|
||||||
if template_arg is not None:
|
|
||||||
return cg.new_Pvariable(id_obj, template_arg, lambda_expr)
|
|
||||||
return cg.new_Pvariable(id_obj, lambda_expr)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
def validate_automation(extra_schema=None, extra_validators=None, single=False):
|
||||||
if extra_schema is None:
|
if extra_schema is None:
|
||||||
extra_schema = {}
|
extra_schema = {}
|
||||||
@@ -277,9 +240,7 @@ async def lambda_condition_to_code(
|
|||||||
args: TemplateArgsType,
|
args: TemplateArgsType,
|
||||||
) -> MockObj:
|
) -> MockObj:
|
||||||
lambda_ = await cg.process_lambda(config, args, return_type=bool)
|
lambda_ = await cg.process_lambda(config, args, return_type=bool)
|
||||||
return new_lambda_pvariable(
|
return cg.new_Pvariable(condition_id, template_arg, lambda_)
|
||||||
condition_id, lambda_, StatelessLambdaCondition, template_arg
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@register_condition(
|
@register_condition(
|
||||||
@@ -445,7 +406,7 @@ async def lambda_action_to_code(
|
|||||||
args: TemplateArgsType,
|
args: TemplateArgsType,
|
||||||
) -> MockObj:
|
) -> MockObj:
|
||||||
lambda_ = await cg.process_lambda(config, args, return_type=cg.void)
|
lambda_ = await cg.process_lambda(config, args, return_type=cg.void)
|
||||||
return new_lambda_pvariable(action_id, lambda_, StatelessLambdaAction, template_arg)
|
return cg.new_Pvariable(action_id, template_arg, lambda_)
|
||||||
|
|
||||||
|
|
||||||
@register_action(
|
@register_action(
|
||||||
|
|||||||
@@ -155,7 +155,6 @@ DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Compon
|
|||||||
InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter)
|
InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter)
|
||||||
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Component)
|
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Component)
|
||||||
LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
|
LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
|
||||||
StatelessLambdaFilter = binary_sensor_ns.class_("StatelessLambdaFilter", Filter)
|
|
||||||
SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter, cg.Component)
|
SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter, cg.Component)
|
||||||
|
|
||||||
_LOGGER = getLogger(__name__)
|
_LOGGER = getLogger(__name__)
|
||||||
@@ -300,7 +299,7 @@ async def lambda_filter_to_code(config, filter_id):
|
|||||||
lambda_ = await cg.process_lambda(
|
lambda_ = await cg.process_lambda(
|
||||||
config, [(bool, "x")], return_type=cg.optional.template(bool)
|
config, [(bool, "x")], return_type=cg.optional.template(bool)
|
||||||
)
|
)
|
||||||
return automation.new_lambda_pvariable(filter_id, lambda_, StatelessLambdaFilter)
|
return cg.new_Pvariable(filter_id, lambda_)
|
||||||
|
|
||||||
|
|
||||||
@register_filter(
|
@register_filter(
|
||||||
|
|||||||
@@ -111,21 +111,6 @@ class LambdaFilter : public Filter {
|
|||||||
std::function<optional<bool>(bool)> f_;
|
std::function<optional<bool>(bool)> f_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Optimized lambda filter for stateless lambdas (no capture).
|
|
||||||
*
|
|
||||||
* Uses function pointer instead of std::function to reduce memory overhead.
|
|
||||||
* Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function).
|
|
||||||
*/
|
|
||||||
class StatelessLambdaFilter : public Filter {
|
|
||||||
public:
|
|
||||||
explicit StatelessLambdaFilter(optional<bool> (*f)(bool)) : f_(f) {}
|
|
||||||
|
|
||||||
optional<bool> new_value(bool value) override { return this->f_(value); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
optional<bool> (*f_)(bool);
|
|
||||||
};
|
|
||||||
|
|
||||||
class SettleFilter : public Filter, public Component {
|
class SettleFilter : public Filter, public Component {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.automation import LambdaAction, StatelessLambdaAction
|
from esphome.automation import LambdaAction
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
|
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
|
||||||
from esphome.components.esp32.const import (
|
from esphome.components.esp32.const import (
|
||||||
@@ -430,9 +430,7 @@ async def logger_log_action_to_code(config, action_id, template_arg, args):
|
|||||||
text = str(cg.statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_)))
|
text = str(cg.statement(esp_log(config[CONF_TAG], config[CONF_FORMAT], *args_)))
|
||||||
|
|
||||||
lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void)
|
lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void)
|
||||||
return automation.new_lambda_pvariable(
|
return cg.new_Pvariable(action_id, template_arg, lambda_)
|
||||||
action_id, lambda_, StatelessLambdaAction, template_arg
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
@@ -457,9 +455,7 @@ async def logger_set_level_to_code(config, action_id, template_arg, args):
|
|||||||
text = str(cg.statement(logger.set_log_level(level)))
|
text = str(cg.statement(logger.set_log_level(level)))
|
||||||
|
|
||||||
lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void)
|
lambda_ = await cg.process_lambda(Lambda(text), args, return_type=cg.void)
|
||||||
return automation.new_lambda_pvariable(
|
return cg.new_Pvariable(action_id, template_arg, lambda_)
|
||||||
action_id, lambda_, StatelessLambdaAction, template_arg
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
||||||
|
|||||||
@@ -261,7 +261,6 @@ ExponentialMovingAverageFilter = sensor_ns.class_(
|
|||||||
)
|
)
|
||||||
ThrottleAverageFilter = sensor_ns.class_("ThrottleAverageFilter", Filter, cg.Component)
|
ThrottleAverageFilter = sensor_ns.class_("ThrottleAverageFilter", Filter, cg.Component)
|
||||||
LambdaFilter = sensor_ns.class_("LambdaFilter", Filter)
|
LambdaFilter = sensor_ns.class_("LambdaFilter", Filter)
|
||||||
StatelessLambdaFilter = sensor_ns.class_("StatelessLambdaFilter", Filter)
|
|
||||||
OffsetFilter = sensor_ns.class_("OffsetFilter", Filter)
|
OffsetFilter = sensor_ns.class_("OffsetFilter", Filter)
|
||||||
MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter)
|
MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter)
|
||||||
ValueListFilter = sensor_ns.class_("ValueListFilter", Filter)
|
ValueListFilter = sensor_ns.class_("ValueListFilter", Filter)
|
||||||
@@ -574,7 +573,7 @@ async def lambda_filter_to_code(config, filter_id):
|
|||||||
lambda_ = await cg.process_lambda(
|
lambda_ = await cg.process_lambda(
|
||||||
config, [(float, "x")], return_type=cg.optional.template(float)
|
config, [(float, "x")], return_type=cg.optional.template(float)
|
||||||
)
|
)
|
||||||
return automation.new_lambda_pvariable(filter_id, lambda_, StatelessLambdaFilter)
|
return cg.new_Pvariable(filter_id, lambda_)
|
||||||
|
|
||||||
|
|
||||||
DELTA_SCHEMA = cv.Schema(
|
DELTA_SCHEMA = cv.Schema(
|
||||||
|
|||||||
@@ -296,21 +296,6 @@ class LambdaFilter : public Filter {
|
|||||||
lambda_filter_t lambda_filter_;
|
lambda_filter_t lambda_filter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Optimized lambda filter for stateless lambdas (no capture).
|
|
||||||
*
|
|
||||||
* Uses function pointer instead of std::function to reduce memory overhead.
|
|
||||||
* Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function).
|
|
||||||
*/
|
|
||||||
class StatelessLambdaFilter : public Filter {
|
|
||||||
public:
|
|
||||||
explicit StatelessLambdaFilter(optional<float> (*lambda_filter)(float)) : lambda_filter_(lambda_filter) {}
|
|
||||||
|
|
||||||
optional<float> new_value(float value) override { return this->lambda_filter_(value); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
optional<float> (*lambda_filter_)(float);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A simple filter that adds `offset` to each value it receives.
|
/// A simple filter that adds `offset` to each value it receives.
|
||||||
class OffsetFilter : public Filter {
|
class OffsetFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ validate_filters = cv.validate_registry("filter", FILTER_REGISTRY)
|
|||||||
# Filters
|
# Filters
|
||||||
Filter = text_sensor_ns.class_("Filter")
|
Filter = text_sensor_ns.class_("Filter")
|
||||||
LambdaFilter = text_sensor_ns.class_("LambdaFilter", Filter)
|
LambdaFilter = text_sensor_ns.class_("LambdaFilter", Filter)
|
||||||
StatelessLambdaFilter = text_sensor_ns.class_("StatelessLambdaFilter", Filter)
|
|
||||||
ToUpperFilter = text_sensor_ns.class_("ToUpperFilter", Filter)
|
ToUpperFilter = text_sensor_ns.class_("ToUpperFilter", Filter)
|
||||||
ToLowerFilter = text_sensor_ns.class_("ToLowerFilter", Filter)
|
ToLowerFilter = text_sensor_ns.class_("ToLowerFilter", Filter)
|
||||||
AppendFilter = text_sensor_ns.class_("AppendFilter", Filter)
|
AppendFilter = text_sensor_ns.class_("AppendFilter", Filter)
|
||||||
@@ -71,7 +70,7 @@ async def lambda_filter_to_code(config, filter_id):
|
|||||||
lambda_ = await cg.process_lambda(
|
lambda_ = await cg.process_lambda(
|
||||||
config, [(cg.std_string, "x")], return_type=cg.optional.template(cg.std_string)
|
config, [(cg.std_string, "x")], return_type=cg.optional.template(cg.std_string)
|
||||||
)
|
)
|
||||||
return automation.new_lambda_pvariable(filter_id, lambda_, StatelessLambdaFilter)
|
return cg.new_Pvariable(filter_id, lambda_)
|
||||||
|
|
||||||
|
|
||||||
@FILTER_REGISTRY.register("to_upper", ToUpperFilter, {})
|
@FILTER_REGISTRY.register("to_upper", ToUpperFilter, {})
|
||||||
|
|||||||
@@ -62,21 +62,6 @@ class LambdaFilter : public Filter {
|
|||||||
lambda_filter_t lambda_filter_;
|
lambda_filter_t lambda_filter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Optimized lambda filter for stateless lambdas (no capture).
|
|
||||||
*
|
|
||||||
* Uses function pointer instead of std::function to reduce memory overhead.
|
|
||||||
* Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function).
|
|
||||||
*/
|
|
||||||
class StatelessLambdaFilter : public Filter {
|
|
||||||
public:
|
|
||||||
explicit StatelessLambdaFilter(optional<std::string> (*lambda_filter)(std::string)) : lambda_filter_(lambda_filter) {}
|
|
||||||
|
|
||||||
optional<std::string> new_value(std::string value) override { return this->lambda_filter_(value); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
optional<std::string> (*lambda_filter_)(std::string);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A simple filter that converts all text to uppercase
|
/// A simple filter that converts all text to uppercase
|
||||||
class ToUpperFilter : public Filter {
|
class ToUpperFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -27,11 +27,21 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
public:
|
public:
|
||||||
TemplatableValue() : type_(NONE) {}
|
TemplatableValue() : type_(NONE) {}
|
||||||
|
|
||||||
template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0> TemplatableValue(F value) : type_(VALUE) {
|
template<typename F>
|
||||||
|
requires(!std::invocable<F, X...>) TemplatableValue(F value) : type_(VALUE) {
|
||||||
new (&this->value_) T(std::move(value));
|
new (&this->value_) T(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0> TemplatableValue(F f) : type_(LAMBDA) {
|
// For stateless lambdas (convertible to function pointer): use function pointer
|
||||||
|
template<typename F>
|
||||||
|
requires std::invocable<F, X...> && std::convertible_to<F, T (*)(X...)> TemplatableValue(F f)
|
||||||
|
: type_(STATELESS_LAMBDA) {
|
||||||
|
this->stateless_f_ = f; // Implicit conversion to function pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// For stateful lambdas (not convertible to function pointer): use std::function
|
||||||
|
template<typename F>
|
||||||
|
requires std::invocable<F, X...> &&(!std::convertible_to<F, T (*)(X...)>) TemplatableValue(F f) : type_(LAMBDA) {
|
||||||
this->f_ = new std::function<T(X...)>(std::move(f));
|
this->f_ = new std::function<T(X...)>(std::move(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +51,8 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
new (&this->value_) T(other.value_);
|
new (&this->value_) T(other.value_);
|
||||||
} else if (type_ == LAMBDA) {
|
} else if (type_ == LAMBDA) {
|
||||||
this->f_ = new std::function<T(X...)>(*other.f_);
|
this->f_ = new std::function<T(X...)>(*other.f_);
|
||||||
|
} else if (type_ == STATELESS_LAMBDA) {
|
||||||
|
this->stateless_f_ = other.stateless_f_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +63,8 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
} else if (type_ == LAMBDA) {
|
} else if (type_ == LAMBDA) {
|
||||||
this->f_ = other.f_;
|
this->f_ = other.f_;
|
||||||
other.f_ = nullptr;
|
other.f_ = nullptr;
|
||||||
|
} else if (type_ == STATELESS_LAMBDA) {
|
||||||
|
this->stateless_f_ = other.stateless_f_;
|
||||||
}
|
}
|
||||||
other.type_ = NONE;
|
other.type_ = NONE;
|
||||||
}
|
}
|
||||||
@@ -78,16 +92,23 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
} else if (type_ == LAMBDA) {
|
} else if (type_ == LAMBDA) {
|
||||||
delete this->f_;
|
delete this->f_;
|
||||||
}
|
}
|
||||||
|
// STATELESS_LAMBDA/NONE: no cleanup needed (function pointer or empty, not heap-allocated)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_value() { return this->type_ != NONE; }
|
bool has_value() { return this->type_ != NONE; }
|
||||||
|
|
||||||
T value(X... x) {
|
T value(X... x) {
|
||||||
if (this->type_ == LAMBDA) {
|
switch (this->type_) {
|
||||||
return (*this->f_)(x...);
|
case STATELESS_LAMBDA:
|
||||||
|
return this->stateless_f_(x...); // Direct function pointer call
|
||||||
|
case LAMBDA:
|
||||||
|
return (*this->f_)(x...); // std::function call
|
||||||
|
case VALUE:
|
||||||
|
return this->value_;
|
||||||
|
case NONE:
|
||||||
|
default:
|
||||||
|
return T{};
|
||||||
}
|
}
|
||||||
// return value also when none
|
|
||||||
return this->type_ == VALUE ? this->value_ : T{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<T> optional_value(X... x) {
|
optional<T> optional_value(X... x) {
|
||||||
@@ -109,11 +130,13 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
NONE,
|
NONE,
|
||||||
VALUE,
|
VALUE,
|
||||||
LAMBDA,
|
LAMBDA,
|
||||||
|
STATELESS_LAMBDA,
|
||||||
} type_;
|
} type_;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
T value_;
|
T value_;
|
||||||
std::function<T(X...)> *f_;
|
std::function<T(X...)> *f_;
|
||||||
|
T (*stateless_f_)(X...);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -79,18 +79,6 @@ template<typename... Ts> class LambdaCondition : public Condition<Ts...> {
|
|||||||
std::function<bool(Ts...)> f_;
|
std::function<bool(Ts...)> f_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Optimized lambda condition for stateless lambdas (no capture).
|
|
||||||
/// Uses function pointer instead of std::function to reduce memory overhead.
|
|
||||||
/// Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function).
|
|
||||||
template<typename... Ts> class StatelessLambdaCondition : public Condition<Ts...> {
|
|
||||||
public:
|
|
||||||
explicit StatelessLambdaCondition(bool (*f)(Ts...)) : f_(f) {}
|
|
||||||
bool check(Ts... x) override { return this->f_(x...); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool (*f_)(Ts...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Ts> class ForCondition : public Condition<Ts...>, public Component {
|
template<typename... Ts> class ForCondition : public Condition<Ts...>, public Component {
|
||||||
public:
|
public:
|
||||||
explicit ForCondition(Condition<> *condition) : condition_(condition) {}
|
explicit ForCondition(Condition<> *condition) : condition_(condition) {}
|
||||||
@@ -202,19 +190,6 @@ template<typename... Ts> class LambdaAction : public Action<Ts...> {
|
|||||||
std::function<void(Ts...)> f_;
|
std::function<void(Ts...)> f_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Optimized lambda action for stateless lambdas (no capture).
|
|
||||||
/// Uses function pointer instead of std::function to reduce memory overhead.
|
|
||||||
/// Memory: 4 bytes (function pointer on 32-bit) vs 32 bytes (std::function).
|
|
||||||
template<typename... Ts> class StatelessLambdaAction : public Action<Ts...> {
|
|
||||||
public:
|
|
||||||
explicit StatelessLambdaAction(void (*f)(Ts...)) : f_(f) {}
|
|
||||||
|
|
||||||
void play(Ts... x) override { this->f_(x...); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void (*f_)(Ts...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Ts> class IfAction : public Action<Ts...> {
|
template<typename... Ts> class IfAction : public Action<Ts...> {
|
||||||
public:
|
public:
|
||||||
explicit IfAction(Condition<Ts...> *condition) : condition_(condition) {}
|
explicit IfAction(Condition<Ts...> *condition) : condition_(condition) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user