Implement N4279, Improved insertion interface for unique-key maps.

2015-08-09  Ville Voutilainen  <ville.voutilainen@gmail.com>

	Implement N4279, Improved insertion interface for unique-key maps.
	* include/bits/stl_map.h (try_emplace, insert_or_assign): New.
	* include/bits/stl_tree.h (_M_get_insert_unique_pos,
	_M_get_insert_equal_pos, _M_get_insert_hint_unique_pos,
	_M_get_insert_hint_equal_pos): Make public.
	* include/bits/unordered_map.h (try_emplace, insert_or_assign): New.
	* testsuite/23_containers/map/modifiers/insert_or_assign/1.cc:
	Likewise.
	* testsuite/23_containers/map/modifiers/try_emplace/1.cc: Likewise.
	* testsuite/23_containers/unordered_map/modifiers/insert_or_assign.cc:
	Likewise.
	* testsuite/23_containers/unordered_map/modifiers/try_emplace.cc:
	Likewise.

From-SVN: r226743
This commit is contained in:
Ville Voutilainen 2015-08-09 01:57:13 +03:00 committed by Ville Voutilainen
parent d0920fa2df
commit b95170d380
8 changed files with 1696 additions and 1 deletions

View File

@ -1,3 +1,19 @@
2015-08-09 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement N4279, Improved insertion interface for unique-key maps.
* include/bits/stl_map.h (try_emplace, insert_or_assign): New.
* include/bits/stl_tree.h (_M_get_insert_unique_pos,
_M_get_insert_equal_pos, _M_get_insert_hint_unique_pos,
_M_get_insert_hint_equal_pos): Make public.
* include/bits/unordered_map.h (try_emplace, insert_or_assign): New.
* testsuite/23_containers/map/modifiers/insert_or_assign/1.cc:
Likewise.
* testsuite/23_containers/map/modifiers/try_emplace/1.cc: Likewise.
* testsuite/23_containers/unordered_map/modifiers/insert_or_assign.cc:
Likewise.
* testsuite/23_containers/unordered_map/modifiers/try_emplace.cc:
Likewise.
2015-08-08 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement N4089 Safe conversions in unique_ptr<T[]> (LWG 2118)

View File

@ -591,7 +591,123 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::forward<_Args>(__args)...);
}
#endif
#if __cplusplus > 201402L
/**
* @brief Attempts to build and insert a std::pair into the %map.
*
* @param __k Key to use for finding a possibly existing pair in
* the map.
* @param __args Arguments used to generate the .second for a new pair
* instance.
*
* @return A pair, of which the first element is an iterator that points
* to the possibly inserted pair, and the second is a bool that
* is true if the pair was actually inserted.
*
* This function attempts to build and insert a (key, value) %pair into
* the %map.
* A %map relies on unique keys and thus a %pair is only inserted if its
* first element (the key) is not already present in the %map.
* If a %pair is not inserted, this function has no effect.
*
* Insertion requires logarithmic time.
*/
template <typename... _Args>
pair<iterator, bool>
try_emplace(const key_type& __k, _Args&&... __args)
{
iterator __i = lower_bound(__k);
if (__i == end() || key_comp()(__k, (*__i).first))
{
__i = emplace_hint(__i, std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
return {__i, true};
}
return {__i, false};
}
// move-capable overload
template <typename... _Args>
pair<iterator, bool>
try_emplace(key_type&& __k, _Args&&... __args)
{
iterator __i = lower_bound(__k);
if (__i == end() || key_comp()(__k, (*__i).first))
{
__i = emplace_hint(__i, std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
return {__i, true};
}
return {__i, false};
}
/**
* @brief Attempts to build and insert a std::pair into the %map.
*
* @param __hint An iterator that serves as a hint as to where the
* pair should be inserted.
* @param __k Key to use for finding a possibly existing pair in
* the map.
* @param __args Arguments used to generate the .second for a new pair
* instance.
* @return An iterator that points to the element with key of the
* std::pair built from @a __args (may or may not be that
* std::pair).
*
* This function is not concerned about whether the insertion took place,
* and thus does not return a boolean like the single-argument
* try_emplace() does. However, if insertion did not take place,
* this function has no effect.
* Note that the first parameter is only a hint and can potentially
* improve the performance of the insertion process. A bad hint would
* cause no gains in efficiency.
*
* See
* https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
* for more on @a hinting.
*
* Insertion requires logarithmic time (if the hint is not taken).
*/
template <typename... _Args>
iterator
try_emplace(const_iterator __hint, const key_type& __k,
_Args&&... __args)
{
iterator __i;
auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k);
if (__true_hint.second)
__i = emplace_hint(iterator(__true_hint.second),
std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
else
__i = iterator(__true_hint.first);
return __i;
}
// move-capable overload
template <typename... _Args>
iterator
try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
{
iterator __i;
auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k);
if (__true_hint.second)
__i = emplace_hint(iterator(__true_hint.second),
std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
else
__i = iterator(__true_hint.first);
return __i;
}
#endif
/**
* @brief Attempts to insert a std::pair into the %map.
@ -688,6 +804,122 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
insert(_InputIterator __first, _InputIterator __last)
{ _M_t._M_insert_unique(__first, __last); }
#if __cplusplus > 201402L
/**
* @brief Attempts to insert or assign a std::pair into the %map.
* @param __k Key to use for finding a possibly existing pair in
* the map.
* @param __obj Argument used to generate the .second for a pair
* instance.
*
* @return A pair, of which the first element is an iterator that
* points to the possibly inserted pair, and the second is
* a bool that is true if the pair was actually inserted.
*
* This function attempts to insert a (key, value) %pair into the %map.
* A %map relies on unique keys and thus a %pair is only inserted if its
* first element (the key) is not already present in the %map.
* If the %pair was already in the %map, the .second of the %pair
* is assigned from __obj.
*
* Insertion requires logarithmic time.
*/
template <typename _Obj>
pair<iterator, bool>
insert_or_assign(const key_type& __k, _Obj&& __obj)
{
iterator __i = lower_bound(__k);
if (__i == end() || key_comp()(__k, (*__i).first))
{
__i = emplace_hint(__i, std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
return {__i, true};
}
(*__i).second = std::forward<_Obj>(__obj);
return {__i, false};
}
// move-capable overload
template <typename _Obj>
pair<iterator, bool>
insert_or_assign(key_type&& __k, _Obj&& __obj)
{
iterator __i = lower_bound(__k);
if (__i == end() || key_comp()(__k, (*__i).first))
{
__i = emplace_hint(__i, std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
return {__i, true};
}
(*__i).second = std::forward<_Obj>(__obj);
return {__i, false};
}
/**
* @brief Attempts to insert or assign a std::pair into the %map.
* @param __hint An iterator that serves as a hint as to where the
* pair should be inserted.
* @param __k Key to use for finding a possibly existing pair in
* the map.
* @param __obj Argument used to generate the .second for a pair
* instance.
*
* @return An iterator that points to the element with key of
* @a __x (may or may not be the %pair passed in).
*
* This function attempts to insert a (key, value) %pair into the %map.
* A %map relies on unique keys and thus a %pair is only inserted if its
* first element (the key) is not already present in the %map.
* If the %pair was already in the %map, the .second of the %pair
* is assigned from __obj.
*
* Insertion requires logarithmic time.
*/
template <typename _Obj>
iterator
insert_or_assign(const_iterator __hint,
const key_type& __k, _Obj&& __obj)
{
iterator __i;
auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k);
if (__true_hint.second)
{
return emplace_hint(iterator(__true_hint.second),
std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
}
__i = iterator(__true_hint.first);
(*__i).second = std::forward<_Obj>(__obj);
return __i;
}
// move-capable overload
template <typename _Obj>
iterator
insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
{
iterator __i;
auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k);
if (__true_hint.second)
{
return emplace_hint(iterator(__true_hint.second),
std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
}
__i = iterator(__true_hint.first);
(*__i).second = std::forward<_Obj>(__obj);
return __i;
}
#endif
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.

View File

@ -731,7 +731,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
private:
pair<_Base_ptr, _Base_ptr>
_M_get_insert_unique_pos(const key_type& __k);
@ -746,6 +745,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_get_insert_hint_equal_pos(const_iterator __pos,
const key_type& __k);
private:
#if __cplusplus >= 201103L
template<typename _Arg, typename _NodeGen>
iterator

View File

@ -410,6 +410,122 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
emplace_hint(const_iterator __pos, _Args&&... __args)
{ return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); }
#if __cplusplus > 201402L
/**
* @brief Attempts to build and insert a std::pair into the
* %unordered_map.
*
* @param __k Key to use for finding a possibly existing pair in
* the unordered_map.
* @param __args Arguments used to generate the .second for a
* new pair instance.
*
* @return A pair, of which the first element is an iterator that points
* to the possibly inserted pair, and the second is a bool that
* is true if the pair was actually inserted.
*
* This function attempts to build and insert a (key, value) %pair into
* the %unordered_map.
* An %unordered_map relies on unique keys and thus a %pair is only
* inserted if its first element (the key) is not already present in the
* %unordered_map.
* If a %pair is not inserted, this function has no effect.
*
* Insertion requires amortized constant time.
*/
template <typename... _Args>
pair<iterator, bool>
try_emplace(const key_type& __k, _Args&&... __args)
{
iterator __i = find(__k);
if (__i == end())
{
__i = emplace(std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Args>(__args)...))
.first;
return {__i, true};
}
return {__i, false};
}
// move-capable overload
template <typename... _Args>
pair<iterator, bool>
try_emplace(key_type&& __k, _Args&&... __args)
{
iterator __i = find(__k);
if (__i == end())
{
__i = emplace(std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Args>(__args)...))
.first;
return {__i, true};
}
return {__i, false};
}
/**
* @brief Attempts to build and insert a std::pair into the
* %unordered_map.
*
* @param __hint An iterator that serves as a hint as to where the pair
* should be inserted.
* @param __k Key to use for finding a possibly existing pair in
* the unordered_map.
* @param __args Arguments used to generate the .second for a
* new pair instance.
* @return An iterator that points to the element with key of the
* std::pair built from @a __args (may or may not be that
* std::pair).
*
* This function is not concerned about whether the insertion took place,
* and thus does not return a boolean like the single-argument emplace()
* does. However, if insertion did not take place,
* this function has no effect.
* Note that the first parameter is only a hint and can potentially
* improve the performance of the insertion process. A bad hint would
* cause no gains in efficiency.
*
* See
* https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
* for more on @a hinting.
*
* Insertion requires amortized constant time.
*/
template <typename... _Args>
iterator
try_emplace(const_iterator __hint, const key_type& __k,
_Args&&... __args)
{
iterator __i = find(__k);
if (__i == end())
__i = emplace_hint(__hint, std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
return __i;
}
// move-capable overload
template <typename... _Args>
iterator
try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
{
iterator __i = find(__k);
if (__i == end())
__i = emplace_hint(__hint, std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Args>(__args)...));
return __i;
}
#endif
//@{
/**
* @brief Attempts to insert a std::pair into the %unordered_map.
@ -499,6 +615,124 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
insert(initializer_list<value_type> __l)
{ _M_h.insert(__l); }
#if __cplusplus > 201402L
/**
* @brief Attempts to insert a std::pair into the %unordered_map.
* @param __k Key to use for finding a possibly existing pair in
* the map.
* @param __obj Argument used to generate the .second for a pair
* instance.
*
* @return A pair, of which the first element is an iterator that
* points to the possibly inserted pair, and the second is
* a bool that is true if the pair was actually inserted.
*
* This function attempts to insert a (key, value) %pair into the
* %unordered_map. An %unordered_map relies on unique keys and thus a
* %pair is only inserted if its first element (the key) is not already
* present in the %unordered_map.
* If the %pair was already in the %unordered_map, the .second of
* the %pair is assigned from __obj.
*
* Insertion requires amortized constant time.
*/
template <typename _Obj>
pair<iterator, bool>
insert_or_assign(const key_type& __k, _Obj&& __obj)
{
iterator __i = find(__k);
if (__i == end())
{
__i = emplace(std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(std::forward<_Obj>(__obj)))
.first;
return {__i, true};
}
(*__i).second = std::forward<_Obj>(__obj);
return {__i, false};
}
// move-capable overload
template <typename _Obj>
pair<iterator, bool>
insert_or_assign(key_type&& __k, _Obj&& __obj)
{
iterator __i = find(__k);
if (__i == end())
{
__i = emplace(std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(std::forward<_Obj>(__obj)))
.first;
return {__i, true};
}
(*__i).second = std::forward<_Obj>(__obj);
return {__i, false};
}
/**
* @brief Attempts to insert a std::pair into the %unordered_map.
* @param __hint An iterator that serves as a hint as to where the
* pair should be inserted.
* @param __k Key to use for finding a possibly existing pair in
* the unordered_map.
* @param __obj Argument used to generate the .second for a pair
* instance.
* @return An iterator that points to the element with key of
* @a __x (may or may not be the %pair passed in).
*
* This function is not concerned about whether the insertion took place,
* and thus does not return a boolean like the single-argument insert()
* does.
* If the %pair was already in the %unordered map, the .second of
* the %pair is assigned from __obj.
* Note that the first parameter is only a hint and can
* potentially improve the performance of the insertion process. A bad
* hint would cause no gains in efficiency.
*
* See
* https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints
* for more on @a hinting.
*
* Insertion requires amortized constant time.
*/
template <typename _Obj>
iterator
insert_or_assign(const_iterator __hint, const key_type& __k,
_Obj&& __obj)
{
iterator __i = find(__k);
if (__i == end())
{
return emplace_hint(__hint, std::piecewise_construct,
std::forward_as_tuple(__k),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
}
(*__i).second = std::forward<_Obj>(__obj);
return __i;
}
// move-capable overload
template <typename _Obj>
iterator
insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
{
iterator __i = find(__k);
if (__i == end())
{
return emplace_hint(__hint, std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::forward_as_tuple(
std::forward<_Obj>(__obj)));
}
(*__i).second = std::forward<_Obj>(__obj);
return __i;
}
#endif
//@{
/**
* @brief Erases an element from an %unordered_map.

View File

@ -0,0 +1,299 @@
// { dg-options "-std=gnu++17" }
// Copyright (C) 2015 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/>.
#include <utility>
#include <map>
#include <testsuite_hooks.h>
bool test __attribute__((unused)) = true;
struct Val
{
bool moved_from_ctor = false;
bool moved_from_assign = false;
int val;
Val(int val = 0) : val(val) {}
Val(const Val& other) : val(other.val)
{
}
Val(Val&& other) : val(other.val)
{
other.moved_from_ctor = true;
}
Val& operator=(Val&& other)
{
val = other.val;
other.moved_from_assign = true;
}
Val& operator=(const Val& other)
{
val = other.val;
}
};
bool operator<(const Val& a, const Val& b)
{
return a.val < b.val;
}
void test01()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test02()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test03()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(std::move(k1), std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(std::move(k2), std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test04()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), std::move(k1), std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), std::move(k2), std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test05()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(1, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test06()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(m.begin(), 1, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test07()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(k1, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(k2, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test08()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), k1, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(m.begin(), k2, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
return 0;
}

View File

@ -0,0 +1,291 @@
// { dg-options "-std=gnu++17" }
// Copyright (C) 2015 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/>.
#include <utility>
#include <map>
#include <testsuite_hooks.h>
bool test __attribute__((unused)) = true;
struct Val
{
bool moved_from_ctor = false;
bool moved_from_assign = false;
int val;
Val(int val = 0) : val(val) {}
Val(const Val& other) : val(other.val)
{
}
Val(Val&& other) : val(other.val)
{
other.moved_from_ctor = true;
}
Val& operator=(Val&& other)
{
val = other.val;
other.moved_from_assign = true;
}
};
bool operator<(const Val& a, const Val& b)
{
return a.val < b.val;
}
void test01()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test02()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test03()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(std::move(k1), std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(std::move(k2), std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test04()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), std::move(k1), std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(m.begin(), std::move(k2), std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test05()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(0, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(1, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test06()
{
typedef std::map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), 0, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(m.begin(), 1, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test07()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(k1, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(k2, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test08()
{
typedef std::map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), k1, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(m.begin(), k2, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
return 0;
}

View File

@ -0,0 +1,315 @@
// { dg-options "-std=gnu++17" }
// Copyright (C) 2015 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/>.
#include <utility>
#include <unordered_map>
#include <testsuite_hooks.h>
bool test __attribute__((unused)) = true;
struct Val
{
bool moved_from_ctor = false;
bool moved_from_assign = false;
int val;
Val(int val = 0) : val(val) {}
Val(const Val& other) : val(other.val)
{
}
Val(Val&& other) : val(other.val)
{
other.moved_from_ctor = true;
}
Val& operator=(Val&& other)
{
val = other.val;
other.moved_from_assign = true;
}
Val& operator=(const Val& other)
{
val = other.val;
}
};
bool operator==(const Val& a, const Val& b)
{
return a.val == b.val;
}
namespace std
{
template <> struct hash<Val>
{
using result_type = size_t;
using argument_type = Val;
size_t
operator()(const Val& t) const
noexcept
{
return hash<int>{}(t.val);
}
};
}
void test01()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test02()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test03()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(std::move(k1), std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(std::move(k2), std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test04()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), std::move(k1), std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
v1.moved_from_assign = false;
auto res3 = m.insert_or_assign(m.begin(), std::move(k2), std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test05()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(0, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(1, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test06()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), 0, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.insert_or_assign(m.begin(), 1, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test07()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(k1, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(k2, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test08()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.insert_or_assign(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.insert_or_assign(m.begin(), k1, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 6);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.insert_or_assign(m.begin(), k2, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 6);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
return 0;
}

View File

@ -0,0 +1,308 @@
// { dg-options "-std=gnu++17" }
// Copyright (C) 2015 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/>.
#include <utility>
#include <unordered_map>
#include <functional>
#include <testsuite_hooks.h>
bool test __attribute__((unused)) = true;
struct Val
{
bool moved_from_ctor = false;
bool moved_from_assign = false;
int val;
Val(int val = 0) : val(val) {}
Val(const Val& other) : val(other.val)
{
}
Val(Val&& other) : val(other.val)
{
other.moved_from_ctor = true;
}
Val& operator=(Val&& other)
{
val = other.val;
other.moved_from_assign = true;
}
};
bool operator==(const Val& a, const Val& b)
{
return a.val == b.val;
}
namespace std
{
template <> struct hash<Val>
{
using result_type = size_t;
using argument_type = Val;
size_t
operator()(const Val& t) const
noexcept
{
return hash<int>{}(t.val);
}
};
}
void test01()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test02()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test03()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(std::move(k1), std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(std::move(k2), std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test04()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), std::move(k1), std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(m.begin(), std::move(k2), std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test05()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(0, std::move(v1));
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(1, std::move(v1));
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test06()
{
typedef std::unordered_map<int, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), 0, std::move(v1));
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
auto res3 = m.try_emplace(m.begin(), 1, std::move(v1));
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test07()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(0, Val(5));
VERIFY(res1.second);
VERIFY(res1.first != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(k1, v1);
VERIFY(!res2.second);
VERIFY(res2.first == res1.first);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(k2, v1);
VERIFY(res3.first != res1.first && res3.first != m.end());
VERIFY(res3.second);
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
void test08()
{
typedef std::unordered_map<Val, Val> Map;
Map m;
auto res1 = m.try_emplace(m.begin(), 0, Val(5));
VERIFY(res1 != m.end());
VERIFY(m[0].val == 5);
Val k1{0};
Val v1{6};
VERIFY(m.size() == 1);
auto res2 = m.try_emplace(m.begin(), k1, v1);
VERIFY(res2 == res1);
VERIFY(m[0].val == 5);
VERIFY(!k1.moved_from_ctor);
VERIFY(!k1.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 1);
Val k2{1};
auto res3 = m.try_emplace(m.begin(), k2, v1);
VERIFY(res3 != res1 && res3 != m.end());
VERIFY(m[0].val == 5);
VERIFY(m[1].val == 6);
VERIFY(!k2.moved_from_ctor);
VERIFY(!k2.moved_from_assign);
VERIFY(!v1.moved_from_ctor);
VERIFY(!v1.moved_from_assign);
VERIFY(m.size() == 2);
}
int main()
{
test01();
test02();
test03();
test04();
test05();
test06();
test07();
test08();
return 0;
}