diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 4980c0224c..d91c1ab287 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -36,6 +36,9 @@ template class TemplatableStringValue : public TemplatableValue class TemplatableKeyValuePair { public: + // Keys are always string literals from YAML dictionary keys (e.g., "code", "event") + // and never templatable values or lambdas. Only the value parameter can be a lambda/template. + // Using pass-by-value with std::move allows optimal performance for both lvalues and rvalues. template TemplatableKeyValuePair(std::string key, T value) : key(std::move(key)), value(value) {} std::string key; TemplatableStringValue value; @@ -47,14 +50,15 @@ template class HomeAssistantServiceCallAction : public Action void set_service(T service) { this->service_ = service; } - template void add_data(std::string key, T value) { - this->data_.push_back(TemplatableKeyValuePair(key, value)); - } + // Keys are always string literals from the Python code generation (e.g., cg.add(var.add_data("tag_id", templ))). + // The value parameter can be a lambda/template, but keys are never templatable. + // Using pass-by-value allows the compiler to optimize for both lvalues and rvalues. + template void add_data(std::string key, T value) { this->data_.emplace_back(std::move(key), value); } template void add_data_template(std::string key, T value) { - this->data_template_.push_back(TemplatableKeyValuePair(key, value)); + this->data_template_.emplace_back(std::move(key), value); } template void add_variable(std::string key, T value) { - this->variables_.push_back(TemplatableKeyValuePair(key, value)); + this->variables_.emplace_back(std::move(key), value); } void play(Ts... x) override {