mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 22:26:36 +00:00
Optimize TemplatableValue memory (#9202)
This commit is contained in:
parent
15ef93ccc9
commit
c74e5e0f04
@ -27,20 +27,67 @@ 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>
|
template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0> TemplatableValue(F value) : type_(VALUE) {
|
||||||
TemplatableValue(F value) : type_(VALUE), value_(std::move(value)) {}
|
new (&this->value_) T(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0>
|
template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0> TemplatableValue(F f) : type_(LAMBDA) {
|
||||||
TemplatableValue(F f) : type_(LAMBDA), f_(f) {}
|
this->f_ = new std::function<T(X...)>(std::move(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor
|
||||||
|
TemplatableValue(const TemplatableValue &other) : type_(other.type_) {
|
||||||
|
if (type_ == VALUE) {
|
||||||
|
new (&this->value_) T(other.value_);
|
||||||
|
} else if (type_ == LAMBDA) {
|
||||||
|
this->f_ = new std::function<T(X...)>(*other.f_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move constructor
|
||||||
|
TemplatableValue(TemplatableValue &&other) noexcept : type_(other.type_) {
|
||||||
|
if (type_ == VALUE) {
|
||||||
|
new (&this->value_) T(std::move(other.value_));
|
||||||
|
} else if (type_ == LAMBDA) {
|
||||||
|
this->f_ = other.f_;
|
||||||
|
other.f_ = nullptr;
|
||||||
|
}
|
||||||
|
other.type_ = NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assignment operators
|
||||||
|
TemplatableValue &operator=(const TemplatableValue &other) {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~TemplatableValue();
|
||||||
|
new (this) TemplatableValue(other);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplatableValue &operator=(TemplatableValue &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
this->~TemplatableValue();
|
||||||
|
new (this) TemplatableValue(std::move(other));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TemplatableValue() {
|
||||||
|
if (type_ == VALUE) {
|
||||||
|
this->value_.~T();
|
||||||
|
} else if (type_ == LAMBDA) {
|
||||||
|
delete this->f_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
if (this->type_ == LAMBDA) {
|
||||||
return this->f_(x...);
|
return (*this->f_)(x...);
|
||||||
}
|
}
|
||||||
// return value also when none
|
// return value also when none
|
||||||
return this->value_;
|
return this->type_ == VALUE ? this->value_ : T{};
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<T> optional_value(X... x) {
|
optional<T> optional_value(X... x) {
|
||||||
@ -58,14 +105,16 @@ template<typename T, typename... X> class TemplatableValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum {
|
enum : uint8_t {
|
||||||
NONE,
|
NONE,
|
||||||
VALUE,
|
VALUE,
|
||||||
LAMBDA,
|
LAMBDA,
|
||||||
} type_;
|
} type_;
|
||||||
|
|
||||||
T value_{};
|
union {
|
||||||
std::function<T(X...)> f_{};
|
T value_;
|
||||||
|
std::function<T(X...)> *f_;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Base class for all automation conditions.
|
/** Base class for all automation conditions.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user