Make detail::json_ref do less work by deferring moves/copies

This commit is contained in:
Nikita Ofitserov 2017-07-24 12:29:06 +03:00
parent 0f4978e503
commit 897879bccb

View file

@ -7088,50 +7088,55 @@ struct json_ref
typedef BasicJsonType value_type; typedef BasicJsonType value_type;
json_ref(value_type&& value) json_ref(value_type&& value)
: value_(std::move(value)) : value_ref_(&value)
, is_rvalue_(true) , is_rvalue_(true)
{} {}
json_ref(const value_type& value) json_ref(const value_type& value)
: value_(value) : value_ref_(const_cast<value_type*>(&value))
, is_rvalue_(false) , is_rvalue_(false)
{} {}
json_ref(std::initializer_list<json_ref> init) json_ref(std::initializer_list<json_ref> init)
: value_(init) : owned_value_(init)
, is_rvalue_(true) , is_rvalue_(true)
{} {
value_ref_ = &owned_value_;
}
template <class... Args> template <class... Args>
json_ref(Args... args) json_ref(Args... args)
: value_(std::forward<Args>(args)...) : owned_value_(std::forward<Args>(args)...)
, is_rvalue_(true) , is_rvalue_(true)
{} {
value_ref_ = &owned_value_;
}
value_type moved() const value_type moved_or_copied() const
{ {
if (is_rvalue_) if (is_rvalue_)
{ {
return std::move(value_); return std::move(*value_ref_);
} }
else else
{ {
return value_; return *value_ref_;
} }
} }
value_type const& operator*() const value_type const& operator*() const
{ {
return value_; return *static_cast<value_type const*>(value_ref_);
} }
value_type const* operator->() const value_type const* operator->() const
{ {
return &value_; return static_cast<value_type const*>(value_ref_);
} }
private: private:
mutable value_type value_; value_type * value_ref_;
mutable value_type owned_value_;
bool is_rvalue_; bool is_rvalue_;
}; };
@ -8747,7 +8752,7 @@ class basic_json
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref) std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
{ {
basic_json element = element_ref.moved(); basic_json element = element_ref.moved_or_copied();
m_value.object->emplace( m_value.object->emplace(
std::move(*((*element.m_value.array)[0].m_value.string)), std::move(*((*element.m_value.array)[0].m_value.string)),
std::move((*element.m_value.array)[1])); std::move((*element.m_value.array)[1]));
@ -9010,7 +9015,7 @@ class basic_json
/////////////////////////////////////// ///////////////////////////////////////
basic_json(const detail::json_ref<basic_json>& ref) basic_json(const detail::json_ref<basic_json>& ref)
: basic_json(ref.moved()) : basic_json(ref.moved_or_copied())
{ {
} }
@ -11935,8 +11940,9 @@ class basic_json
{ {
if (is_object() and init.size() == 2 and (*init.begin())->is_string()) if (is_object() and init.size() == 2 and (*init.begin())->is_string())
{ {
basic_json&& key = init.begin()->moved(); basic_json&& key = init.begin()->moved_or_copied();
push_back(typename object_t::value_type(std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved())); push_back(typename object_t::value_type(
std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
} }
else else
{ {