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:
TemplatableValue() : type_(NONE) {}
template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0>
TemplatableValue(F value) : type_(VALUE), value_(std::move(value)) {}
template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0> TemplatableValue(F value) : type_(VALUE) {
new (&this->value_) T(std::move(value));
}
template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0>
TemplatableValue(F f) : type_(LAMBDA), f_(f) {}
template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0> TemplatableValue(F f) : type_(LAMBDA) {
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; }
T value(X... x) {
if (this->type_ == LAMBDA) {
return this->f_(x...);
return (*this->f_)(x...);
}
// return value also when none
return this->value_;
return this->type_ == VALUE ? this->value_ : T{};
}
optional<T> optional_value(X... x) {
@ -58,14 +105,16 @@ template<typename T, typename... X> class TemplatableValue {
}
protected:
enum {
enum : uint8_t {
NONE,
VALUE,
LAMBDA,
} type_;
T value_{};
std::function<T(X...)> f_{};
union {
T value_;
std::function<T(X...)> *f_;
};
};
/** Base class for all automation conditions.