Use init_array_from helper for optimal codegen

Uses memcpy for trivially copyable types, element-wise copy otherwise.
ESPHOME_DEBUG_ASSERT catches size mismatches in integration tests.
This commit is contained in:
J. Nick Koston
2026-03-27 16:14:53 -10:00
parent f9c2d60b7d
commit 8b42629e3e
2 changed files with 16 additions and 5 deletions
+1 -5
View File
@@ -112,11 +112,7 @@ class AutorepeatFilterBase : public Filter, public Component {
template<size_t N> class AutorepeatFilter : public AutorepeatFilterBase {
public:
explicit AutorepeatFilter(std::initializer_list<AutorepeatFilterTiming> timings) {
ESPHOME_DEBUG_ASSERT(timings.size() == N);
size_t i = 0;
for (const auto &t : timings) {
this->timings_storage_[i++] = t;
}
init_array_from(this->timings_storage_, timings);
this->timings_ = this->timings_storage_.data();
this->timings_count_ = N;
}
+15
View File
@@ -497,6 +497,21 @@ template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()>
index_type capacity_{0};
};
/// Initialize a std::array from an initializer_list. Uses memcpy for trivially copyable types (optimal codegen),
/// falls back to element-wise copy for non-trivially copyable types (e.g. TemplatableValue).
/// N is set by code generation; ESPHOME_DEBUG_ASSERT catches mismatches in debug/integration tests.
template<typename T, size_t N> inline void init_array_from(std::array<T, N> &dest, std::initializer_list<T> src) {
ESPHOME_DEBUG_ASSERT(src.size() == N);
if constexpr (std::is_trivially_copyable_v<T>) {
__builtin_memcpy(dest.data(), src.begin(), N * sizeof(T));
} else {
size_t i = 0;
for (const auto &v : src) {
dest[i++] = v;
}
}
}
/// Fixed-capacity vector - allocates once at runtime, never reallocates
/// This avoids std::vector template overhead (_M_realloc_insert, _M_default_append)
/// when size is known at initialization but not at compile time