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:
parent
d0920fa2df
commit
b95170d380
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue