Optimize TemplatableValue memory (#9202)

This commit is contained in:
J. Nick Koston 2025-06-26 03:51:51 +02:00 committed by GitHub
parent 15ef93ccc9
commit c74e5e0f04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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.