mirror of
https://github.com/fraillt/bitsery.git
synced 2026-06-08 08:13:56 +00:00
Avoid reinitializing nontrivial std::variant #76
When deserializing into an `std::variant<Ts...>` and the object we're deserializing into already holds the requested variant, then we should try to deserialize into the existing object instead of recreating it if the variant is a nontrivial type. This is important when the object has a default constructor that performs a nontrivial amount of work, or when the object contains heap data that would need to be reallocated when recreating the object.
This commit is contained in:
@@ -54,6 +54,17 @@ namespace bitsery {
|
||||
this->execIndex(index, obj, [this, &des](auto& data, auto index) {
|
||||
constexpr size_t Index = decltype(index)::value;
|
||||
using TElem = typename std::variant_alternative<Index, std::variant<Ts...>>::type;
|
||||
|
||||
// Reinitializing nontrivial types may be expensive especially when they
|
||||
// reference heap data, so if `data` is already holding the requested
|
||||
// variant then we'll deserialize into the existing object
|
||||
if constexpr (!std::is_trivial_v<TElem>) {
|
||||
if (auto item = std::get_if<TElem>(&data)) {
|
||||
this->serializeType(des, *item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TElem item = ::bitsery::Access::create<TElem>();
|
||||
this->serializeType(des, item);
|
||||
data = std::variant<Ts...>(std::in_place_index_t<Index>{}, std::move(item));
|
||||
|
||||
Reference in New Issue
Block a user