diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 17f937d10d..9418170b6d 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -273,18 +273,28 @@ template class WhileLoopContinuation : public Action { WhileAction *parent_; }; +// Wraps a ContinuationAction when Enabled, empty otherwise. +// Lets IfAction elide the else continuation when HasElse is false. +template struct OptionalContinuation { + ContinuationAction action; + explicit OptionalContinuation(Action *parent) : action(parent) {} +}; +template struct OptionalContinuation { + explicit OptionalContinuation(Action * /*parent*/) {} +}; + template class IfAction : public Action { public: explicit IfAction(Condition *condition) : condition_(condition) {} void add_then(const std::initializer_list *> &actions) { this->then_.add_actions(actions); - this->then_.add_action(new ContinuationAction(this)); + this->then_.add_action(&this->then_continuation_); } void add_else(const std::initializer_list *> &actions) requires(HasElse) { this->else_.add_actions(actions); - this->else_.add_action(new ContinuationAction(this)); + this->else_.add_action(&this->else_continuation_.action); } void play_complex(const Ts &...x) override { @@ -316,8 +326,10 @@ template class IfAction : public Action { protected: Condition *condition_; ActionList then_; + ContinuationAction then_continuation_{this}; struct NoElse {}; [[no_unique_address]] std::conditional_t, NoElse> else_; + [[no_unique_address]] OptionalContinuation else_continuation_{this}; }; template class WhileAction : public Action { @@ -326,7 +338,7 @@ template class WhileAction : public Action { void add_then(const std::initializer_list *> &actions) { this->then_.add_actions(actions); - this->then_.add_action(new WhileLoopContinuation(this)); + this->then_.add_action(&this->loop_continuation_); } friend class WhileLoopContinuation; @@ -354,6 +366,7 @@ template class WhileAction : public Action { protected: Condition *condition_; ActionList then_; + WhileLoopContinuation loop_continuation_{this}; }; // Implementation of WhileLoopContinuation::play @@ -388,7 +401,7 @@ template class RepeatAction : public Action { void add_then(const std::initializer_list *> &actions) { this->then_.add_actions(actions); - this->then_.add_action(new RepeatLoopContinuation(this)); + this->then_.add_action(&this->loop_continuation_); } friend class RepeatLoopContinuation; @@ -409,6 +422,7 @@ template class RepeatAction : public Action { protected: ActionList then_; + RepeatLoopContinuation loop_continuation_{this}; }; // Implementation of RepeatLoopContinuation::play