From 703f140fb8dbe977cf5fabecd60e163267b6e227 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Dumont?= Date: Tue, 7 May 2013 20:26:15 +0000 Subject: [PATCH] unordered_base.h: New. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2013-05-07 François Dumont * include/profile/unordered_base.h: New. * include/Makefile.am: Add new profile header. * include/Makefile.in: Regenerate. * include/profile/impl/profiler.h (__profcxx_inefficient_hash_is_on): New macro. * include/profile/unordered_map (std::profile::unordered_map<>): Use new _Unordered_profile base class. Use default implementations for special functions. (std::profile::unordered_multimap<>): Likewise. * include/profile/unordered_set (std::profile::unordered_set<>): Likewise. (std::profile::unordered_multiset<>): Likewise. * testsuite/23_containers/unordered_multiset/55043.cc: Fix MoveOnly equality operator signature. From-SVN: r198698 --- libstdc++-v3/ChangeLog | 17 ++ libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/profile/impl/profiler.h | 9 +- libstdc++-v3/include/profile/unordered_base.h | 262 +++++++++++++++++++++ libstdc++-v3/include/profile/unordered_map | 261 +++++++------------- libstdc++-v3/include/profile/unordered_set | 259 +++++++------------- .../23_containers/unordered_multiset/55043.cc | 2 +- 8 files changed, 464 insertions(+), 348 deletions(-) create mode 100644 libstdc++-v3/include/profile/unordered_base.h diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f9f0a82..e6d8734 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2013-05-07 François Dumont + + * include/profile/unordered_base.h: New. + * include/Makefile.am: Add new profile header. + * include/Makefile.in: Regenerate. + * include/profile/impl/profiler.h + (__profcxx_inefficient_hash_is_on): New macro. + * include/profile/unordered_map (std::profile::unordered_map<>): + Use new _Unordered_profile base class. Use default implementations + for special functions. + (std::profile::unordered_multimap<>): Likewise. + * include/profile/unordered_set (std::profile::unordered_set<>): + Likewise. + (std::profile::unordered_multiset<>): Likewise. + * testsuite/23_containers/unordered_multiset/55043.cc: Fix + MoveOnly equality operator signature. + 2013-05-02 Paolo Carlini * testsuite/tr1/4_metaprogramming/integral_constant/requirements/ diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index b0ea41d..11cb4df 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -788,6 +788,7 @@ profile_builddir = ./profile profile_headers = \ ${profile_srcdir}/array \ ${profile_srcdir}/base.h \ + ${profile_srcdir}/unordered_base.h \ ${profile_srcdir}/unordered_map \ ${profile_srcdir}/unordered_set \ ${profile_srcdir}/vector \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index a644155..b69f757 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -1045,6 +1045,7 @@ profile_builddir = ./profile profile_headers = \ ${profile_srcdir}/array \ ${profile_srcdir}/base.h \ + ${profile_srcdir}/unordered_base.h \ ${profile_srcdir}/unordered_map \ ${profile_srcdir}/unordered_set \ ${profile_srcdir}/vector \ diff --git a/libstdc++-v3/include/profile/impl/profiler.h b/libstdc++-v3/include/profile/impl/profiler.h index d8019cb..081bb64 100644 --- a/libstdc++-v3/include/profile/impl/profiler.h +++ b/libstdc++-v3/include/profile/impl/profiler.h @@ -188,7 +188,7 @@ namespace __gnu_profile _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid()) #define __profcxx_is_on() \ _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_on()) -#define __profcxx__is_off() \ +#define __profcxx_is_off() \ _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_off()) #else #define __profcxx_report() @@ -237,6 +237,8 @@ namespace __gnu_profile // Turn on/off instrumentation for INEFFICIENT_HASH. #if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) +#define __profcxx_inefficient_hash_is_on() \ + __gnu_profile::__is_on() #define __profcxx_hashtable_construct2(__x...) \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_construct(__x)) @@ -244,8 +246,9 @@ namespace __gnu_profile _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_destruct(__x)) #else -#define __profcxx_hashtable_destruct2(__x...) -#define __profcxx_hashtable_construct2(__x...) +#define __profcxx_inefficient_hash_is_on() false +#define __profcxx_hashtable_destruct2(__x...) +#define __profcxx_hashtable_construct2(__x...) #endif // Turn on/off instrumentation for VECTOR_TO_LIST. diff --git a/libstdc++-v3/include/profile/unordered_base.h b/libstdc++-v3/include/profile/unordered_base.h new file mode 100644 index 0000000..81d7694 --- /dev/null +++ b/libstdc++-v3/include/profile/unordered_base.h @@ -0,0 +1,262 @@ +// Profiling unordered containers implementation details -*- C++ -*- + +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +/** @file profile/unordered_base.h + * This file is a GNU profile extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_PROFILE_UNORDERED +#define _GLIBCXX_PROFILE_UNORDERED 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __profile +{ + template + struct _Bucket_index_helper; + + template + struct _Bucket_index_helper<_UnorderedCont, _Value, true> + { + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __node) + { return __node->_M_hash_code % __uc.bucket_count(); } + }; + + template + struct _Bucket_index_helper<_UnorderedCont, _Value, false> + { + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __node) + { return __uc.bucket(__node->_M_v()); } + }; + + template + struct _Bucket_index_helper<_UnorderedCont, + std::pair, false> + { + typedef std::pair _Value; + + static std::size_t + bucket(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __node) + { return __uc.bucket(__node->_M_v().first); } + }; + + template + std::size_t + __get_bucket_index(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __node) + { + using __bucket_index_helper + = _Bucket_index_helper<_UnorderedCont, _Value, _Cache_hash_code>; + return __bucket_index_helper::bucket(__uc, __node); + } + + template + struct _Equal_helper; + + template + struct _Equal_helper<_UnorderedCont, _Value, true> + { + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __lhs, + const __detail::_Hash_node<_Value, true>* __rhs) + { + return __lhs->_M_hash_code == __rhs->_M_hash_code + && __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); + } + }; + + template + struct _Equal_helper<_UnorderedCont, _Value, false> + { + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __lhs, + const __detail::_Hash_node<_Value, false>* __rhs) + { return __uc.key_eq()(__lhs->_M_v(), __rhs->_M_v()); } + }; + + template + struct _Equal_helper<_UnorderedCont, std::pair, true> + { + typedef std::pair _Value; + + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, true>* __lhs, + const __detail::_Hash_node<_Value, true>* __rhs) + { + return __lhs->_M_hash_code == __rhs->_M_hash_code + && __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); + } + }; + + template + struct _Equal_helper<_UnorderedCont, std::pair, false> + { + typedef std::pair _Value; + + static std::size_t + are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, false>* __lhs, + const __detail::_Hash_node<_Value, false>* __rhs) + { return __uc.key_eq()(__lhs->_M_v().first, __rhs->_M_v().first); } + }; + + template + bool + __are_equal(const _UnorderedCont& __uc, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __lhs, + const __detail::_Hash_node<_Value, _Cache_hash_code>* __rhs) + { + using __equal_helper + = _Equal_helper<_UnorderedCont, _Value, _Cache_hash_code>; + return __equal_helper::are_equal(__uc, __lhs, __rhs); + } + + template + class _Unordered_profile + { + _UnorderedCont& + _M_conjure() + { return *(static_cast<_UnorderedCont*>(this)); } + + using __unique_keys = std::integral_constant; + + protected: + _Unordered_profile() + { + auto& __uc = _M_conjure(); + __profcxx_hashtable_construct(&__uc, __uc.bucket_count()); + __profcxx_hashtable_construct2(&__uc); + } + _Unordered_profile(const _Unordered_profile&) + : _Unordered_profile() { } + _Unordered_profile(_Unordered_profile&&) + : _Unordered_profile() { } + + ~_Unordered_profile() noexcept + { + auto& __uc = _M_conjure(); + __profcxx_hashtable_destruct(&__uc, __uc.bucket_count(), __uc.size()); + _M_profile_destruct(); + } + + _Unordered_profile& + operator=(const _Unordered_profile&) = default; + + _Unordered_profile& + operator=(_Unordered_profile&&) = default; + + void + _M_profile_destruct() + { + if (!__profcxx_inefficient_hash_is_on()) + return; + + _M_profile_destruct(__unique_keys()); + } + + private: + void + _M_profile_destruct(std::true_type); + + void + _M_profile_destruct(std::false_type); + }; + + template + void + _Unordered_profile<_UnorderedCont, _Unique_keys>:: + _M_profile_destruct(std::true_type) + { + auto& __uc = _M_conjure(); + std::size_t __hops = 0, __lc = 0, __chain = 0; + auto __it = __uc.begin(); + while (__it != __uc.end()) + { + auto __bkt = __get_bucket_index(__uc, __it._M_cur); + auto __lit = __uc.begin(__bkt); + auto __lend = __uc.end(__bkt); + for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) + ++__chain; + if (__chain) + { + ++__chain; + __lc = __lc > __chain ? __lc : __chain; + __hops += __chain * (__chain - 1) / 2; + __chain = 0; + } + } + __profcxx_hashtable_destruct2(&__uc, __lc, __uc.size(), __hops); + } + + template + void + _Unordered_profile<_UnorderedCont, _Unique_keys>:: + _M_profile_destruct(std::false_type) + { + auto& __uc = _M_conjure(); + std::size_t __hops = 0, __lc = 0, __chain = 0, __unique_size = 0; + auto __it = __uc.begin(); + while (__it != __uc.end()) + { + auto __bkt = __get_bucket_index(__uc, __it._M_cur); + auto __lit = __uc.begin(__bkt); + auto __lend = __uc.end(__bkt); + auto __pit = __it; + ++__unique_size; + for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) + { + if (!__are_equal(__uc, __pit._M_cur, __it._M_cur)) + { + ++__chain; + ++__unique_size; + __pit = __it; + } + } + if (__chain) + { + ++__chain; + __lc = __lc > __chain ? __lc : __chain; + __hops += __chain * (__chain - 1) / 2; + __chain = 0; + } + } + __profcxx_hashtable_destruct2(&__uc, __lc, __unique_size, __hops); + } + +} // namespace __profile +} // namespace std + +#endif diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map index f594ab8..ac5fecc 100644 --- a/libstdc++-v3/include/profile/unordered_map +++ b/libstdc++-v3/include/profile/unordered_map @@ -34,6 +34,7 @@ # include #include +#include #define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE @@ -48,10 +49,18 @@ namespace __profile typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator > > class unordered_map - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile, + true> { typedef typename _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -72,11 +81,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__n, __hf, __eql, __a) + { } template unordered_map(_InputIterator __f, _InputIterator __l, @@ -84,85 +90,60 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_map(const unordered_map& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_map(const unordered_map&) = default; unordered_map(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__x) + { } - unordered_map(unordered_map&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_map(unordered_map&&) = default; + + explicit + unordered_map(const allocator_type& __a) + : _Base(__a) + { } + + unordered_map(const unordered_map& __umap, + const allocator_type& __a) + : _Base(__umap, __a) + { } + + unordered_map(unordered_map&& __umap, + const allocator_type& __a) + : _Base(std::move(__umap._M_base()), __a) + { } unordered_map(initializer_list __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_map& - operator=(const unordered_map& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_map&) = default; unordered_map& - operator=(unordered_map&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_map&&) = default; unordered_map& operator=(initializer_list __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_map() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - - _Base& - _M_base() noexcept { return *this; } - - const _Base& - _M_base() const noexcept { return *this; } - void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); - _Base::clear(); + this->_M_profile_destruct(); + _Base::clear(); } template @@ -247,14 +228,6 @@ namespace __profile _M_profile_resize(__old_size); } - void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - // operator[] mapped_type& operator[](const _Key& __k) @@ -276,7 +249,8 @@ namespace __profile void swap(unordered_map& __x) - { _Base::swap(__x); } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x._M_base()); } void rehash(size_type __n) { @@ -293,29 +267,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(__it->first); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template, typename _Alloc = std::allocator > > class unordered_multimap - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile, + false> { typedef typename _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -373,85 +333,69 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__n, __hf, __eql, __a) + { } + template unordered_multimap(_InputIterator __f, _InputIterator __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_multimap(const unordered_multimap& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multimap(const unordered_multimap&) = default; unordered_multimap(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__x) + { } - unordered_multimap(unordered_multimap&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multimap(unordered_multimap&&) = default; + + explicit + unordered_multimap(const allocator_type& __a) + : _Base(__a) + { } + + unordered_multimap(const unordered_multimap& __ummap, + const allocator_type& __a) + : _Base(__ummap._M_base(), __a) + { } + + unordered_multimap(unordered_multimap&& __ummap, + const allocator_type& __a) + : _Base(std::move(__ummap._M_base()), __a) + { } unordered_multimap(initializer_list __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_multimap& - operator=(const unordered_multimap& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_multimap&) = default; unordered_multimap& - operator=(unordered_multimap&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_multimap&&) = default; unordered_multimap& operator=(initializer_list __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_multimap() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void clear() noexcept { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), + __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); - _Base::clear(); + this->_M_profile_destruct(); + _Base::clear(); } template @@ -536,18 +480,12 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void swap(unordered_multimap& __x) - { _Base::swap(__x); } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x._M_base()); } - void rehash(size_type __n) + void + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -562,29 +500,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(__it->first); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template #include +#include #define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc> #define _GLIBCXX_STD_BASE _GLIBCXX_STD_C::_GLIBCXX_BASE @@ -44,14 +45,22 @@ namespace __profile { /** @brief Unordered_set wrapper with performance instrumentation. */ template, + typename _Hash = std::hash<_Key>, typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator<_Key> > class unordered_set - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile, + true> { typedef _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -71,11 +80,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__n, __hf, __eql, __a) + { } template unordered_set(_InputIterator __f, _InputIterator __l, @@ -83,84 +89,64 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_set(const unordered_set& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_set(const unordered_set&) = default; unordered_set(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + : _Base(__x) + { } - unordered_set(unordered_set&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - __profcxx_hashtable_construct2(this); - } + unordered_set(unordered_set&&) = default; + + explicit + unordered_set(const allocator_type& __a) + : _Base(__a) + { } + + unordered_set(const unordered_set& __uset, + const allocator_type& __a) + : _Base(__uset._M_base(), __a) + { } + + unordered_set(unordered_set&& __uset, + const allocator_type& __a) + : _Base(std::move(__uset._M_base()), __a) + { } unordered_set(initializer_list __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_set& - operator=(const unordered_set& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_set&) = default; unordered_set& - operator=(unordered_set&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_set&&) = default; unordered_set& operator=(initializer_list __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_set() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void swap(unordered_set& __x) - { - _Base::swap(__x); - } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x); } void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); + this->_M_profile_destruct(); _Base::clear(); } @@ -240,14 +226,7 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void rehash(size_type __n) + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -262,29 +241,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(*__it); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template @@ -312,14 +268,23 @@ namespace __profile /** @brief Unordered_multiset wrapper with performance instrumentation. */ template, - typename _Pred = std::equal_to<_Value>, - typename _Alloc = std::allocator<_Value> > + typename _Hash = std::hash<_Value>, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value> > class unordered_multiset - : public _GLIBCXX_STD_BASE + : public _GLIBCXX_STD_BASE, + public _Unordered_profile, + false> { typedef _GLIBCXX_STD_BASE _Base; + _Base& + _M_base() noexcept { return *this; } + + const _Base& + _M_base() const noexcept { return *this; } + public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -339,10 +304,8 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__n, __hf, __eql, __a) + { } template unordered_multiset(_InputIterator __f, _InputIterator __l, @@ -350,80 +313,64 @@ namespace __profile const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__f, __l, __n, __hf, __eql, __a) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__f, __l, __n, __hf, __eql, __a) + { } - unordered_multiset(const unordered_multiset& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multiset(const unordered_multiset&) = default; unordered_multiset(const _Base& __x) - : _Base(__x) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + : _Base(__x) + { } - unordered_multiset(unordered_multiset&& __x) - : _Base(std::move(__x)) - { - __profcxx_hashtable_construct(this, _Base::bucket_count()); - } + unordered_multiset(unordered_multiset&&) = default; + + explicit + unordered_multiset(const allocator_type& __a) + : _Base(__a) + { } + + unordered_multiset(const unordered_multiset& __umset, + const allocator_type& __a) + : _Base(__umset._M_base(), __a) + { } + + unordered_multiset(unordered_multiset&& __umset, + const allocator_type& __a) + : _Base(std::move(__umset._M_base()), __a) + { } unordered_multiset(initializer_list __l, size_type __n = 0, const hasher& __hf = hasher(), const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) - : _Base(__l, __n, __hf, __eql, __a) { } + : _Base(__l, __n, __hf, __eql, __a) + { } unordered_multiset& - operator=(const unordered_multiset& __x) - { - *static_cast<_Base*>(this) = __x; - return *this; - } + operator=(const unordered_multiset&) = default; unordered_multiset& - operator=(unordered_multiset&& __x) - { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); - return *this; - } + operator=(unordered_multiset&&) = default; unordered_multiset& operator=(initializer_list __l) { - this->clear(); - this->insert(__l); + _M_base() = __l; return *this; } - ~unordered_multiset() noexcept - { - __profcxx_hashtable_destruct(this, _Base::bucket_count(), - _Base::size()); - _M_profile_destruct(); - } - void swap(unordered_multiset& __x) - { - _Base::swap(__x); - } + noexcept( noexcept(__x._M_base().swap(__x)) ) + { _Base::swap(__x); } void clear() noexcept { __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size()); - _M_profile_destruct(); + this->_M_profile_destruct(); _Base::clear(); } @@ -502,14 +449,7 @@ namespace __profile } void - insert(const value_type* __first, const value_type* __last) - { - size_type __old_size = _Base::bucket_count(); - _Base::insert(__first, __last); - _M_profile_resize(__old_size); - } - - void rehash(size_type __n) + rehash(size_type __n) { size_type __old_size = _Base::bucket_count(); _Base::rehash(__n); @@ -524,29 +464,6 @@ namespace __profile if (__old_size != __new_size) __profcxx_hashtable_resize(this, __old_size, __new_size); } - - void - _M_profile_destruct() - { - size_type __hops = 0, __lc = 0, __chain = 0; - iterator __it = this->begin(); - while (__it != this->end()) - { - size_type __bkt = this->bucket(*__it); - auto __lit = this->begin(__bkt); - auto __lend = this->end(__bkt); - for (++__it, ++__lit; __lit != __lend; ++__it, ++__lit) - ++__chain; - if (__chain) - { - ++__chain; - __lc = __lc > __chain ? __lc : __chain; - __hops += __chain * (__chain - 1) / 2; - __chain = 0; - } - } - __profcxx_hashtable_destruct2(this, __lc, _Base::size(), __hops); - } }; template diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc index 9d71cff..c80ce55 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc @@ -30,7 +30,7 @@ struct MoveOnly }; struct equal { - bool operator()(const MoveOnly&, const MoveOnly) const { return true; } + bool operator()(const MoveOnly&, const MoveOnly&) const { return true; } }; struct hash { std::size_t operator()(const MoveOnly&) const { return 0; } -- 2.7.4