QHash: optimize value(key) and key(value) callers
... by not injecting potentially-expensive temporary objects into the caller's stack frame. Default arguments are a convenient way to avoid overloads, but if the defaulted argument isn't a Trivial Type, and the common use case is not to pass the extra argument explicitly, the construction of the temporary can dominate the call's runtime. Since QHash is generic code, we don't know whether T or Key are expensive or cheap to construct, so use overloading instead of default arguments to avoid injecting needless code into call sites. [ChangeLog][QtCore][Potentially Source-Incompatible Changes][QHash/QMultiHash] The value(key) and key(value) functions are now overloaded on presence of the defaultValue (was: defaulted argument) to avoid injecting temporary objects into the caller's stack frame. Task-number: QTBUG-98117 Change-Id: I80fdd5436f3de3e4bbe20242fe45916aef62ff0c Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
14b0e2fb1e
commit
7fe5611365
@ -1865,14 +1865,15 @@ size_t qHash(long double key, size_t seed) noexcept
|
||||
\sa count(), QMultiHash::contains()
|
||||
*/
|
||||
|
||||
/*! \fn template <class Key, class T> T QHash<Key, T>::value(const Key &key, const T &defaultValue = T()) const
|
||||
/*! \fn template <class Key, class T> T QHash<Key, T>::value(const Key &key) const
|
||||
\fn template <class Key, class T> T QHash<Key, T>::value(const Key &key, const T &defaultValue) const
|
||||
\overload
|
||||
|
||||
Returns the value associated with the \a key.
|
||||
|
||||
If the hash contains no item with the \a key, the function
|
||||
returns \a defaultValue, which is a \l{default-constructed value} if the
|
||||
parameter has not been specified.
|
||||
returns \a defaultValue, or a \l{default-constructed value} if this
|
||||
parameter has not been supplied.
|
||||
*/
|
||||
|
||||
/*! \fn template <class Key, class T> T &QHash<Key, T>::operator[](const Key &key)
|
||||
@ -1935,11 +1936,13 @@ size_t qHash(long double key, size_t seed) noexcept
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <class Key, class T> Key QHash<Key, T>::key(const T &value, const Key &defaultKey = Key()) const
|
||||
\fn template <class Key, class T> Key QHash<Key, T>::key(const T &value) const
|
||||
\fn template <class Key, class T> Key QHash<Key, T>::key(const T &value, const Key &defaultKey) const
|
||||
\since 4.3
|
||||
|
||||
Returns the first key mapped to \a value, or \a defaultKey if the
|
||||
hash contains no item mapped to \a value.
|
||||
Returns the first key mapped to \a value. If the hash contains no item
|
||||
mapped to \a value, returns \a defaultKey, or a \l{default-constructed
|
||||
value}{default-constructed key} if this parameter has not been supplied.
|
||||
|
||||
This function can be slow (\l{linear time}), because QHash's
|
||||
internal data structure is optimized for fast lookup by key, not
|
||||
@ -2899,14 +2902,14 @@ size_t qHash(long double key, size_t seed) noexcept
|
||||
\sa keys(), values()
|
||||
*/
|
||||
|
||||
/*! \fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key, const T &defaultValue = T()) const
|
||||
\overload
|
||||
/*! \fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key) const
|
||||
\fn template <class Key, class T> T QMultiHash<Key, T>::value(const Key &key, const T &defaultValue) const
|
||||
|
||||
Returns the value associated with the \a key.
|
||||
|
||||
If the hash contains no item with the \a key, the function
|
||||
returns \a defaultValue, which is a \l{default-constructed value} if the
|
||||
parameter has not been specified.
|
||||
returns \a defaultValue, or a \l{default-constructed value} if this
|
||||
parameter has not been supplied.
|
||||
|
||||
If there are multiple
|
||||
items for the \a key in the hash, the value of the most recently
|
||||
@ -3054,11 +3057,13 @@ size_t qHash(long double key, size_t seed) noexcept
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value, const Key &defaultKey = Key()) const
|
||||
\fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value) const
|
||||
\fn template <class Key, class T> Key QMultiHash<Key, T>::key(const T &value, const Key &defaultKey) const
|
||||
\since 4.3
|
||||
|
||||
Returns the first key mapped to \a value, or \a defaultKey if the
|
||||
hash contains no item mapped to \a value.
|
||||
Returns the first key mapped to \a value. If the hash contains no item
|
||||
mapped to \a value, returns \a defaultKey, or a \l{default-constructed
|
||||
value}{default-constructed key} if this parameter has not been supplied.
|
||||
|
||||
This function can be slow (\l{linear time}), because QMultiHash's
|
||||
internal data structure is optimized for fast lookup by key, not
|
||||
|
@ -926,28 +926,64 @@ public:
|
||||
return contains(key) ? 1 : 0;
|
||||
}
|
||||
|
||||
Key key(const T &value, const Key &defaultKey = Key()) const noexcept
|
||||
private:
|
||||
const Key *keyImpl(const T &value) const noexcept
|
||||
{
|
||||
if (d) {
|
||||
const_iterator i = begin();
|
||||
while (i != end()) {
|
||||
if (i.value() == value)
|
||||
return i.key();
|
||||
return &i.key();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultKey;
|
||||
return nullptr;
|
||||
}
|
||||
T value(const Key &key, const T &defaultValue = T()) const noexcept
|
||||
|
||||
public:
|
||||
Key key(const T &value) const noexcept
|
||||
{
|
||||
if (auto *k = keyImpl(value))
|
||||
return *k;
|
||||
else
|
||||
return Key();
|
||||
}
|
||||
Key key(const T &value, const Key &defaultKey) const noexcept
|
||||
{
|
||||
if (auto *k = keyImpl(value))
|
||||
return *k;
|
||||
else
|
||||
return defaultKey;
|
||||
}
|
||||
|
||||
private:
|
||||
T *valueImpl(const Key &key) const noexcept
|
||||
{
|
||||
if (d) {
|
||||
Node *n = d->findNode(key);
|
||||
if (n)
|
||||
return n->value;
|
||||
return &n->value;
|
||||
}
|
||||
return defaultValue;
|
||||
return nullptr;
|
||||
}
|
||||
public:
|
||||
T value(const Key &key) const noexcept
|
||||
{
|
||||
if (T *v = valueImpl(key))
|
||||
return *v;
|
||||
else
|
||||
return T();
|
||||
}
|
||||
|
||||
T value(const Key &key, const T &defaultValue) const noexcept
|
||||
{
|
||||
if (T *v = valueImpl(key))
|
||||
return *v;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
T &operator[](const Key &key)
|
||||
{
|
||||
detach();
|
||||
@ -1427,30 +1463,63 @@ public:
|
||||
return d->findNode(key) != nullptr;
|
||||
}
|
||||
|
||||
Key key(const T &value, const Key &defaultKey = Key()) const noexcept
|
||||
private:
|
||||
const Key *keyImpl(const T &value) const noexcept
|
||||
{
|
||||
if (d) {
|
||||
auto i = d->begin();
|
||||
while (i != d->end()) {
|
||||
Chain *e = i.node()->value;
|
||||
if (e->contains(value))
|
||||
return i.node()->key;
|
||||
return &i.node()->key;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultKey;
|
||||
return nullptr;
|
||||
}
|
||||
T value(const Key &key, const T &defaultValue = T()) const noexcept
|
||||
public:
|
||||
Key key(const T &value) const noexcept
|
||||
{
|
||||
if (auto *k = keyImpl(value))
|
||||
return *k;
|
||||
else
|
||||
return Key();
|
||||
}
|
||||
Key key(const T &value, const Key &defaultKey) const noexcept
|
||||
{
|
||||
if (auto *k = keyImpl(value))
|
||||
return *k;
|
||||
else
|
||||
return defaultKey;
|
||||
}
|
||||
|
||||
private:
|
||||
T *valueImpl(const Key &key) const noexcept
|
||||
{
|
||||
if (d) {
|
||||
Node *n = d->findNode(key);
|
||||
if (n) {
|
||||
Q_ASSERT(n->value);
|
||||
return n->value->value;
|
||||
return &n->value->value;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
return nullptr;
|
||||
}
|
||||
public:
|
||||
T value(const Key &key) const noexcept
|
||||
{
|
||||
if (auto *v = valueImpl(key))
|
||||
return *v;
|
||||
else
|
||||
return T();
|
||||
}
|
||||
T value(const Key &key, const T &defaultValue) const noexcept
|
||||
{
|
||||
if (auto *v = valueImpl(key))
|
||||
return *v;
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
T &operator[](const Key &key)
|
||||
|
Loading…
Reference in New Issue
Block a user