commit dd690a5f164326c552c2450af6270ec27e9bfd8e Author: Ollie Wild Date: Tue Aug 7 16:34:05 2012 -0500 2012-08-03 Ollie Wild * include/bits/hashtable.h (_M_emplace_bucket): New function. * include/bits/hashtable_policy.h (operator[](key_type&&)): Replace _M_insert_bucket call with _M_emplace_bucket. * testsuite/23_containers/unordered_map/operators/2.cc: New test. 2012-08-04 Paolo Carlini Revert: diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 2faf0b3..869b0e9 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -588,6 +588,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator _M_insert_bucket(_Arg&&, size_type, __hash_code); + template + iterator + _M_emplace_bucket(size_type, __hash_code, _Args&&... __args); + template std::pair @@ -1356,6 +1360,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + // Insert v in bucket n (assumes no element with its key already present). + template + template + typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, + _Traits>::iterator + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_emplace_bucket(size_type __n, __hash_code __code, _Args&&... __args) + { + // First build the node to get access to the hash code + __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...); + __try + { + + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + std::pair __do_rehash + = _M_rehash_policy._M_need_rehash(_M_bucket_count, + _M_element_count, 1); + + if (__do_rehash.first) + { + const key_type& __k = this->_M_extract()(__node->_M_v); + __n = __hash_code_base::_M_bucket_index(__k, __code, + __do_rehash.second); + } + + this->_M_store_code(__node, __code); + if (__do_rehash.first) + _M_rehash(__do_rehash.second, __saved_state); + + _M_insert_bucket_begin(__n, __node); + ++_M_element_count; + return iterator(__node); + } + __catch(...) + { + _M_deallocate_node(__node); + __throw_exception_again; + } + } + // Insert v if no element with its key is already present. template_M_find_node(__n, __k, __code); if (!__p) - return __h->_M_insert_bucket(std::make_pair(std::move(__k), - mapped_type()), - __n, __code)->second; + return __h->_M_emplace_bucket(__n, __code, + std::move(__k), mapped_type())->second; return (__p->_M_v).second; } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/operators/2.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/operators/2.cc new file mode 100644 index 0000000..1940fa2 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/operators/2.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2012 +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 23.5.4 template class unordered_map + +// This test verifies that the value type of a unordered_map need not be +// default copyable. + +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +#include +#include + +struct Mapped { + Mapped() = default; + explicit Mapped(const Mapped&) = default; +}; + +void foo() +{ + using __gnu_test::rvalstruct; + + std::unordered_map m1; + m1[0] = Mapped(); + + std::unordered_map m2; + m2[0] = rvalstruct(13); +}