hashtable.h (_Hashtable<>::emplace, [...]): Add.

2011-12-09  François Dumont <fdumont@gcc.gnu.org>

	* include/bits/hashtable.h (_Hashtable<>::emplace,
	_Hashtable<>::emplace_hint): Add.
	* include/debug/unordered_set (unordered_set<>::emplace,
	unordered_set<>::emplace_hint, unordered_multiset<>::emplace,
	unordered_multiset<>::emplace_hint): Add.
	* include/profile/unordered_set: Likewise.
	* include/debug/unordered_map (unordered_map<>::emplace,
	unordered_map<>::emplace_hint, unordered_multimap<>::emplace,
	unordered_multimap<>::emplace_hint): Add.
	* include/profile/unordered_map: Likewise.
	* testsuite/23_containers/unordered_map/modifiers/emplace.cc: New.
	* testsuite/23_containers/unordered_multimap/modifiers/emplace.cc:
	New.
	* testsuite/23_containers/unordered_set/modifiers/emplace.cc: New.
	* testsuite/23_containers/unordered_multiset/modifiers/emplace.cc:
	New.
	* testsuite/util/testsuite_container_traits.h
	(traits_base::has_emplace): Add and defined as std::true_type for
	unordered containers.
	* testsuite/util/exception/safety.h (emplace, emplace_hint): Add and
	use them in basic_safety exception test case.
	* doc/xml/manual/status_cxx2011.xml: Update unordered containers
	status.

From-SVN: r182174
This commit is contained in:
François Dumont 2011-12-09 20:01:04 +00:00
parent 60ef5d4e7f
commit 9b81593bbc
11 changed files with 780 additions and 5 deletions

View File

@ -1,3 +1,29 @@
2011-12-09 François Dumont <fdumont@gcc.gnu.org>
* include/bits/hashtable.h (_Hashtable<>::emplace,
_Hashtable<>::emplace_hint): Add.
* include/debug/unordered_set (unordered_set<>::emplace,
unordered_set<>::emplace_hint, unordered_multiset<>::emplace,
unordered_multiset<>::emplace_hint): Add.
* include/profile/unordered_set: Likewise.
* include/debug/unordered_map (unordered_map<>::emplace,
unordered_map<>::emplace_hint, unordered_multimap<>::emplace,
unordered_multimap<>::emplace_hint): Add.
* include/profile/unordered_map: Likewise.
* testsuite/23_containers/unordered_map/modifiers/emplace.cc: New.
* testsuite/23_containers/unordered_multimap/modifiers/emplace.cc:
New.
* testsuite/23_containers/unordered_set/modifiers/emplace.cc: New.
* testsuite/23_containers/unordered_multiset/modifiers/emplace.cc:
New.
* testsuite/util/testsuite_container_traits.h
(traits_base::has_emplace): Add and defined as std::true_type for
unordered containers.
* testsuite/util/exception/safety.h (emplace, emplace_hint): Add and
use them in basic_safety exception test case.
* doc/xml/manual/status_cxx2011.xml: Update unordered containers
status.
2011-12-08 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/bits/atomic_base.h (__calculate_memory_order): Rename to...

View File

@ -1403,11 +1403,10 @@ particular release.
<entry>Missing emplace members</entry>
</row>
<row>
<?dbhtml bgcolor="#B0B0B0" ?>
<entry>23.2.5</entry>
<entry>Unordered associative containers</entry>
<entry>Partial</entry>
<entry>Missing emplace members</entry>
<entry>Y</entry>
<entry/>
</row>
<row>
<entry>23.3</entry>

View File

@ -467,6 +467,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Insert_Conv_Type;
protected:
template<typename... _Args>
std::pair<iterator, bool>
_M_emplace(std::true_type, _Args&&... __args);
template<typename... _Args>
iterator
_M_emplace(std::false_type, _Args&&... __args);
template<typename _Arg>
std::pair<iterator, bool>
_M_insert(_Arg&&, std::true_type);
@ -476,7 +484,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert(_Arg&&, std::false_type);
public:
// Insert and erase
// Emplace, insert and erase
template<typename... _Args>
_Insert_Return_Type
emplace(_Args&&... __args)
{ return _M_emplace(integral_constant<bool, __unique_keys>(),
std::forward<_Args>(__args)...); }
template<typename... _Args>
iterator
emplace_hint(const_iterator, _Args&&... __args)
{ return _Insert_Conv_Type()(emplace(std::forward<_Args>(__args)...)); }
_Insert_Return_Type
insert(const value_type& __v)
{ return _M_insert(__v, integral_constant<bool, __unique_keys>()); }
@ -1160,6 +1179,128 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __prev_n;
}
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
template<typename... _Args>
std::pair<typename _Hashtable<_Key, _Value, _Allocator,
_ExtractKey, _Equal, _H1,
_H2, _Hash, _RehashPolicy,
__chc, __cit, __uk>::iterator, bool>
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_emplace(std::true_type, _Args&&... __args)
{
// First build the node to get access to the hash code
_Node* __new_node = _M_allocate_node(std::forward<_Args>(__args)...);
__try
{
const key_type& __k = this->_M_extract(__new_node->_M_v);
typename _Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k);
size_type __bkt
= this->_M_bucket_index(__k, __code, _M_bucket_count);
if (_Node* __p = _M_find_node(__bkt, __k, __code))
{
// There is already an equivalent node, no insertion
_M_deallocate_node(__new_node);
return std::make_pair(iterator(__p), false);
}
// We are going to insert this node
this->_M_store_code(__new_node, __code);
const _RehashPolicyState& __saved_state
= _M_rehash_policy._M_state();
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
if (__do_rehash.first)
{
_M_rehash(__do_rehash.second, __saved_state);
__bkt = this->_M_bucket_index(__k, __code, _M_bucket_count);
}
if (_M_buckets[__bkt])
_M_insert_after(__bkt, _M_buckets[__bkt], __new_node);
else
_M_insert_bucket_begin(__bkt, __new_node);
++_M_element_count;
return std::make_pair(iterator(__new_node), true);
}
__catch(...)
{
_M_deallocate_node(__new_node);
__throw_exception_again;
}
}
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
bool __chc, bool __cit, bool __uk>
template<typename... _Args>
typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy,
__chc, __cit, __uk>::iterator
_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_emplace(std::false_type, _Args&&... __args)
{
const _RehashPolicyState& __saved_state = _M_rehash_policy._M_state();
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
// First build the node to get its hash code
_Node* __new_node = _M_allocate_node(std::forward<_Args>(__args)...);
__try
{
const key_type& __k = this->_M_extract(__new_node->_M_v);
typename _Hashtable::_Hash_code_type __code
= this->_M_hash_code(__k);
this->_M_store_code(__new_node, __code);
size_type __bkt
= this->_M_bucket_index(__k, __code, _M_bucket_count);
// Second find the node, avoid rehash if compare throws.
_Node* __prev = _M_find_node(__bkt, __k, __code);
if (__do_rehash.first)
{
_M_rehash(__do_rehash.second, __saved_state);
__bkt = this->_M_bucket_index(__k, __code, _M_bucket_count);
// __prev is still valid because rehash do not invalidate nodes
}
if (__prev)
// Insert after the previous equivalent node
_M_insert_after(__bkt, __prev, __new_node);
else if (_M_buckets[__bkt])
// Bucket is not empty and the inserted node has no equivalent in
// the hashtable. We must insert the new node at the beginning or
// end of the bucket to preserve equivalent elements relative
// positions.
if (__bkt != _M_begin_bucket_index)
// We insert the new node at the beginning
_M_insert_after(__bkt, _M_buckets[__bkt], __new_node);
else
// We insert the new node at the end
_M_insert_after(__bkt, _M_bucket_end(__bkt), __new_node);
else
_M_insert_bucket_begin(__bkt, __new_node);
++_M_element_count;
return iterator(__new_node);
}
__catch(...)
{
_M_deallocate_node(__new_node);
__throw_exception_again;
}
}
// Insert v in bucket n (assumes no element with its key already present).
template<typename _Key, typename _Value,
typename _Allocator, typename _ExtractKey, typename _Equal,
@ -1300,7 +1441,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_deallocate_node(__new_node);
__throw_exception_again;
}
}
template<typename _Key, typename _Value,

View File

@ -204,6 +204,29 @@ namespace __debug
cend(size_type __b) const
{ return const_local_iterator(_Base::cend(__b), __b, this); }
template<typename... _Args>
std::pair<iterator, bool>
emplace(_Args&&... __args)
{
size_type __bucket_count = this->bucket_count();
std::pair<_Base_iterator, bool> __res
= _Base::emplace(std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __hint, _Args&&... __args)
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
_Base_iterator __it = _Base::emplace_hint(__hint.base(),
std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
std::pair<iterator, bool>
insert(const value_type& __obj)
{
@ -587,6 +610,29 @@ namespace __debug
cend(size_type __b) const
{ return const_local_iterator(_Base::cend(__b), __b, this); }
template<typename... _Args>
iterator
emplace(_Args&&... __args)
{
size_type __bucket_count = this->bucket_count();
_Base_iterator __it
= _Base::emplace(std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __hint, _Args&&... __args)
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
_Base_iterator __it = _Base::emplace_hint(__hint.base(),
std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
iterator
insert(const value_type& __obj)
{

View File

@ -204,6 +204,29 @@ namespace __debug
cend(size_type __b) const
{ return const_local_iterator(_Base::cend(__b), __b, this); }
template<typename... _Args>
std::pair<iterator, bool>
emplace(_Args&&... __args)
{
size_type __bucket_count = this->bucket_count();
std::pair<_Base_iterator, bool> __res
= _Base::emplace(std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __hint, _Args&&... __args)
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
_Base_iterator __it = _Base::emplace_hint(__hint.base(),
std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
std::pair<iterator, bool>
insert(const value_type& __obj)
{
@ -582,6 +605,29 @@ namespace __debug
cend(size_type __b) const
{ return const_local_iterator(_Base::cend(__b), __b, this); }
template<typename... _Args>
iterator
emplace(_Args&&... __args)
{
size_type __bucket_count = this->bucket_count();
_Base_iterator __it
= _Base::emplace(std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
template<typename... _Args>
iterator
emplace_hint(const_iterator __hint, _Args&&... __args)
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
_Base_iterator __it = _Base::emplace_hint(__hint.base(),
std::forward<_Args>(__args)...);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
iterator
insert(const value_type& __obj)
{

View File

@ -0,0 +1,116 @@
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2011 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
// <http://www.gnu.org/licenses/>.
// range insert
#include <utility>
#include <tuple>
#include <vector>
#include <unordered_map>
#include <testsuite_hooks.h>
class PathPoint
{
public:
PathPoint(char t, const std::vector<double>& c)
: type(t), coords(c) { }
PathPoint(char t, std::vector<double>&& c)
: type(t), coords(std::move(c)) { }
char getType() const { return type; }
const std::vector<double>& getCoords() const { return coords; }
private:
char type;
std::vector<double> coords;
};
bool test __attribute__((unused)) = true;
void test01()
{
typedef std::unordered_map<char, std::vector<double>> Map;
Map m;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto ret = m.emplace('a', coord1);
VERIFY( ret.second );
VERIFY( m.size() == 1 );
VERIFY( ret.first->first == 'a' );
coord1[0] = 3.0;
ret = m.emplace('a', coord1);
VERIFY( !ret.second );
VERIFY( m.size() == 1 );
VERIFY( ret.first->first == 'a' );
VERIFY( ret.first->second[0] == 0.0 );
auto it = m.emplace_hint(m.begin(), 'b', coord1);
VERIFY( it != m.end() );
VERIFY( it->first == 'b' );
VERIFY( it->second[0] == 3.0 );
double *px = &coord1[0];
ret = m.emplace('c', std::move(coord1));
VERIFY( ret.second );
VERIFY( ret.first->first == 'c' );
VERIFY( &(ret.first->second[0]) == px );
}
void test02()
{
using namespace std;
typedef unordered_map<char, PathPoint> Map;
Map m;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto ret = m.emplace(piecewise_construct,
make_tuple('a'), make_tuple('a', coord1));
VERIFY( ret.second );
VERIFY( m.size() == 1 );
VERIFY( ret.first->first == 'a' );
coord1[0] = 3.0;
ret = m.emplace(piecewise_construct,
make_tuple('a'), make_tuple( 'b', coord1));
VERIFY( !ret.second );
VERIFY( m.size() == 1 );
VERIFY( ret.first->first == 'a' );
VERIFY( ret.first->second.getCoords()[0] == 0.0 );
auto it = m.emplace_hint(m.begin(), piecewise_construct,
make_tuple('b'), make_tuple('c', coord1));
VERIFY( it != m.end() );
VERIFY( it->first == 'b' );
VERIFY( it->second.getCoords()[0] == 3.0 );
double *px = &coord1[0];
ret = m.emplace(piecewise_construct,
make_tuple('c'), make_tuple('d', move(coord1)));
VERIFY( ret.second );
VERIFY( ret.first->first == 'c' );
VERIFY( &(ret.first->second.getCoords()[0]) == px );
}
int main()
{
test01();
test02();
return 0;
}

View File

@ -0,0 +1,110 @@
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2011 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
// <http://www.gnu.org/licenses/>.
// range insert
#include <tuple>
#include <vector>
#include <unordered_map>
#include <testsuite_hooks.h>
class PathPoint
{
public:
PathPoint(char t, const std::vector<double>& c)
: type(t), coords(c) { }
PathPoint(char t, std::vector<double>&& c)
: type(t), coords(std::move(c)) { }
char getType() const { return type; }
const std::vector<double>& getCoords() const { return coords; }
private:
char type;
std::vector<double> coords;
};
bool test __attribute__((unused)) = true;
void test01()
{
typedef std::unordered_multimap<char, std::vector<double>> MMap;
MMap mm;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto it = mm.emplace('a', coord1);
VERIFY( mm.size() == 1 );
VERIFY( it->first == 'a' );
coord1[0] = 3.0;
it = mm.emplace('a', coord1);
VERIFY( mm.size() == 2 );
VERIFY( it->first == 'a' );
VERIFY( it->second[0] == 3.0 );
it = mm.emplace_hint(mm.begin(), 'b', coord1);
VERIFY( it != mm.end() );
VERIFY( it->first == 'b' );
VERIFY( it->second[0] == 3.0 );
double *px = &coord1[0];
it = mm.emplace('c', std::move(coord1));
VERIFY( it->first == 'c' );
VERIFY( &(it->second[0]) == px );
}
void test02()
{
using namespace std;
typedef unordered_multimap<char, PathPoint> Map;
Map m;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto it = m.emplace(piecewise_construct,
make_tuple('a'), make_tuple('a', coord1));
VERIFY( m.size() == 1 );
VERIFY( it->first == 'a' );
coord1[0] = 3.0;
it = m.emplace(piecewise_construct,
make_tuple('a'), make_tuple( 'b', coord1));
VERIFY( m.size() == 2 );
VERIFY( it->first == 'a' );
VERIFY( it->second.getCoords()[0] == 3.0 );
it = m.emplace_hint(m.begin(), piecewise_construct,
make_tuple('b'), make_tuple('c', coord1));
VERIFY( it != m.end() );
VERIFY( it->first == 'b' );
VERIFY( it->second.getCoords()[0] == 3.0 );
double *px = &coord1[0];
it = m.emplace(piecewise_construct,
make_tuple('c'), make_tuple('d', move(coord1)));
VERIFY( it->first == 'c' );
VERIFY( &(it->second.getCoords()[0]) == px );
}
int main()
{
test01();
test02();
return 0;
}

View File

@ -0,0 +1,88 @@
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2011 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
// <http://www.gnu.org/licenses/>.
// range insert
#include <vector>
#include <unordered_set>
#include <testsuite_hooks.h>
class PathPoint
{
public:
PathPoint(char t, const std::vector<double>& c)
: type(t), coords(c) { }
PathPoint(char t, std::vector<double>&& c)
: type(t), coords(std::move(c)) { }
char getType() const { return type; }
const std::vector<double>& getCoords() const { return coords; }
private:
char type;
std::vector<double> coords;
};
struct PathPointHasher
{
std::size_t operator() (const PathPoint& __pp) const
{ return __pp.getType(); }
};
struct PathPointEqual
{
bool operator() (const PathPoint& __lhs, const PathPoint& __rhs) const
{ return __lhs.getType() == __rhs.getType(); }
};
bool test __attribute__((unused)) = true;
void test01()
{
typedef std::unordered_multiset<PathPoint, PathPointHasher,
PathPointEqual> Mset;
Mset ms;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto it = ms.emplace('a', coord1);
VERIFY( ms.size() == 1 );
VERIFY( it->getType() == 'a' );
coord1[0] = 3.0;
it = ms.emplace('a', coord1);
VERIFY( ms.size() == 2 );
VERIFY( it->getType() == 'a' );
VERIFY( it->getCoords()[0] == 3.0 );
it = ms.emplace_hint(ms.begin(), 'b', coord1);
VERIFY( it != ms.end() );
VERIFY( it->getType() == 'b' );
VERIFY( it->getCoords()[0] == 3.0 );
double *px = &coord1[0];
it = ms.emplace('c', std::move(coord1));
VERIFY( ms.size() == 4 );
VERIFY( it->getType() == 'c' );
VERIFY( &(it->getCoords()[0]) == px );
}
int main()
{
test01();
return 0;
}

View File

@ -0,0 +1,89 @@
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2011 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
// <http://www.gnu.org/licenses/>.
// range insert
#include <vector>
#include <unordered_set>
#include <testsuite_hooks.h>
class PathPoint
{
public:
PathPoint(char t, const std::vector<double>& c)
: type(t), coords(c) { }
PathPoint(char t, std::vector<double>&& c)
: type(t), coords(std::move(c)) { }
char getType() const { return type; }
const std::vector<double>& getCoords() const { return coords; }
private:
char type;
std::vector<double> coords;
};
struct PathPointHasher
{
std::size_t operator() (const PathPoint& __pp) const
{ return __pp.getType(); }
};
struct PathPointEqual
{
bool operator() (const PathPoint& __lhs, const PathPoint& __rhs) const
{ return __lhs.getType() == __rhs.getType(); }
};
bool test __attribute__((unused)) = true;
void test01()
{
typedef std::unordered_set<PathPoint, PathPointHasher, PathPointEqual> Set;
Set s;
std::vector<double> coord1 = { 0.0, 1.0, 2.0 };
auto ret = s.emplace('a', coord1);
VERIFY( ret.second );
VERIFY( s.size() == 1 );
VERIFY( ret.first->getType() == 'a' );
coord1[0] = 3.0;
ret = s.emplace('a', coord1);
VERIFY( !ret.second );
VERIFY( s.size() == 1 );
VERIFY( ret.first->getType() == 'a' );
VERIFY( ret.first->getCoords()[0] == 0.0 );
auto it = s.emplace_hint(s.begin(), 'b', coord1);
VERIFY( it != s.end() );
VERIFY( it->getType() == 'b' );
VERIFY( it->getCoords()[0] == 3.0 );
double *px = &coord1[0];
ret = s.emplace('c', std::move(coord1));
VERIFY( ret.second );
VERIFY( ret.first->getType() == 'c' );
VERIFY( &(ret.first->getCoords()[0]) == px );
}
int main()
{
test01();
return 0;
}

View File

@ -826,6 +826,110 @@ namespace __gnu_test
operator()(_Tp&, _Tp&) { }
};
template<typename _Tp,
bool = traits<_Tp>::has_emplace::value>
struct emplace;
// Specialization for most containers.
template<typename _Tp>
struct emplace<_Tp, true>
{
typedef _Tp container_type;
typedef typename container_type::value_type value_type;
typedef typename container_type::size_type size_type;
void
operator()(_Tp& __test)
{
try
{
const value_type cv = generate_unique<value_type>();
__test.emplace(cv);
}
catch(const __gnu_cxx::forced_error&)
{ throw; }
}
// Assumes containers start out equivalent.
void
operator()(_Tp& __control, _Tp& __test)
{
try
{
const value_type cv = generate_unique<value_type>();
__test.emplace(cv);
}
catch(const __gnu_cxx::forced_error&)
{ throw; }
}
};
// Specialization, empty.
template<typename _Tp>
struct emplace<_Tp, false>
{
void
operator()(_Tp&) { }
void
operator()(_Tp&, _Tp&) { }
};
template<typename _Tp,
bool = traits<_Tp>::has_emplace::value>
struct emplace_hint;
// Specialization for most containers.
template<typename _Tp>
struct emplace_hint<_Tp, true>
{
typedef _Tp container_type;
typedef typename container_type::value_type value_type;
void
operator()(_Tp& __test)
{
try
{
const value_type cv = generate_unique<value_type>();
const size_type sz = std::distance(__test.begin(), __test.end());
size_type s = generate(sz);
auto i = __test.begin();
std::advance(i, s);
__test.emplace_hint(i, cv);
}
catch(const __gnu_cxx::forced_error&)
{ throw; }
}
// Assumes containers start out equivalent.
void
operator()(_Tp& __control, _Tp& __test)
{
try
{
const value_type cv = generate_unique<value_type>();
const size_type sz = std::distance(__test.begin(), __test.end());
size_type s = generate(sz);
auto i = __test.begin();
std::advance(i, s);
__test.emplace_hint(i, cv);
}
catch(const __gnu_cxx::forced_error&)
{ throw; }
}
};
// Specialization, empty.
template<typename _Tp>
struct emplace_hint<_Tp, false>
{
void
operator()(_Tp&) { }
void
operator()(_Tp&, _Tp&) { }
};
template<typename _Tp, bool = traits<_Tp>::is_associative::value
|| traits<_Tp>::is_unordered::value>
@ -1023,6 +1127,8 @@ namespace __gnu_test
typedef erase_point<container_type> erase_point;
typedef erase_range<container_type> erase_range;
typedef insert_point<container_type> insert_point;
typedef emplace<container_type> emplace;
typedef emplace_hint<container_type> emplace_hint;
typedef pop_front<container_type> pop_front;
typedef pop_back<container_type> pop_back;
typedef push_front<container_type> push_front;
@ -1039,6 +1145,8 @@ namespace __gnu_test
erase_point _M_erasep;
erase_range _M_eraser;
insert_point _M_insertp;
emplace _M_emplace;
emplace_hint _M_emplaceh;
pop_front _M_popf;
pop_back _M_popb;
push_front _M_pushf;
@ -1098,6 +1206,8 @@ namespace __gnu_test
_M_functions.push_back(function_type(base_type::_M_erasep));
_M_functions.push_back(function_type(base_type::_M_eraser));
_M_functions.push_back(function_type(base_type::_M_insertp));
_M_functions.push_back(function_type(base_type::_M_emplace));
_M_functions.push_back(function_type(base_type::_M_emplaceh));
_M_functions.push_back(function_type(base_type::_M_popf));
_M_functions.push_back(function_type(base_type::_M_popb));
_M_functions.push_back(function_type(base_type::_M_pushf));

View File

@ -43,6 +43,7 @@ namespace __gnu_test
typedef std::false_type has_throwing_erase;
typedef std::false_type has_insert;
typedef std::false_type has_insert_after;
typedef std::false_type has_emplace;
typedef std::false_type has_push_pop;
typedef std::false_type has_size_type_constructor;
};
@ -216,6 +217,7 @@ namespace __gnu_test
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_emplace;
};
template<typename _Tp1, typename _Tp2, typename _Tp3,
@ -230,6 +232,7 @@ namespace __gnu_test
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_emplace;
};
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
@ -242,6 +245,7 @@ namespace __gnu_test
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_emplace;
};
template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
@ -254,6 +258,7 @@ namespace __gnu_test
typedef std::true_type has_erase;
typedef std::true_type has_insert;
typedef std::true_type has_emplace;
};
} // namespace __gnu_test