mirror of
https://github.com/boostorg/container.git
synced 2026-01-19 04:02:17 +00:00
Add C++26 transparent "try_emplace" to map and flat_map
This commit is contained in:
@@ -274,142 +274,6 @@ struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
|
||||
typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
|
||||
};
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
BOOST_CONTAINER_STATIC_ASSERT((dtl::is_transparent<less_transparent>::value));
|
||||
{
|
||||
typedef flat_map<int, char, less_transparent> map_t;
|
||||
typedef flat_multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
if(!map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
if(map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!map1.contains(find_me))
|
||||
return false;
|
||||
if(!cmap1.contains(find_me))
|
||||
return false;
|
||||
if(!mmap1.contains(find_me))
|
||||
return false;
|
||||
if(!cmmap1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (map1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (map1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 0)
|
||||
return false;
|
||||
}
|
||||
{
|
||||
typedef flat_map<test::movable_int, char, less_transparent> map_t;
|
||||
|
||||
map_t map1;
|
||||
|
||||
//insert_or_assign
|
||||
if(!map1.insert_or_assign(1, 'e').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
|
||||
//insert_or_assign with hint
|
||||
if(map1.find(2) != map1.end())
|
||||
return false;
|
||||
map_t::iterator i = map1.insert_or_assign(map1.begin(), 2, 'e');
|
||||
if(i != map1.insert_or_assign(map1.end(), 2, 'b'))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// An ordered sequence of std:pair is also ordered by std::pair::first.
|
||||
struct with_lookup_by_first
|
||||
{
|
||||
@@ -486,7 +350,15 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!test_heterogeneous_lookups())
|
||||
if (!test::test_heterogeneous_lookup
|
||||
< flat_map<int, char, less_transparent>
|
||||
, flat_multimap<int, char, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
if (!test::test_heterogeneous_insert
|
||||
< flat_map<test::movable_int, char, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
if (!test_heterogeneous_lookup_by_partial_key())
|
||||
|
||||
@@ -192,6 +192,33 @@ bool node_type_test()
|
||||
if(dst.size() != 5)
|
||||
return false;
|
||||
}
|
||||
{
|
||||
typedef map<test::movable_int, char, test::less_transparent> map_t;
|
||||
typedef multimap<test::movable_int, char, test::less_transparent> mmap_t;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
//extract
|
||||
map1.clear();
|
||||
map1.try_emplace(1, 'a');
|
||||
mmap1.clear();
|
||||
mmap1.emplace(1, 'a');
|
||||
mmap1.emplace(1, 'b');
|
||||
|
||||
if (!map1.extract(1))
|
||||
return false;
|
||||
if (map1.extract(1))
|
||||
return false;
|
||||
|
||||
if (!mmap1.extract(1))
|
||||
return false;
|
||||
if (!mmap1.extract(1))
|
||||
return false;
|
||||
if (mmap1.extract(1))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -259,161 +286,6 @@ void test_merge_from_different_comparison()
|
||||
map1.merge(map2);
|
||||
}
|
||||
|
||||
bool test_heterogeneous_lookups()
|
||||
{
|
||||
{
|
||||
typedef map<int, char, less_transparent> map_t;
|
||||
typedef multimap<int, char, less_transparent> mmap_t;
|
||||
typedef map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
mmap_t mmap1;
|
||||
|
||||
const map_t &cmap1 = map1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
if(!map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
if(map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!map1.contains(find_me))
|
||||
return false;
|
||||
if(!cmap1.contains(find_me))
|
||||
return false;
|
||||
if(!mmap1.contains(find_me))
|
||||
return false;
|
||||
if(!cmmap1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (map1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (map1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 0)
|
||||
return false;
|
||||
|
||||
//extract
|
||||
map1.clear();
|
||||
map1.insert(value_type(1, 'a'));
|
||||
mmap1.clear();
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
|
||||
const test::non_copymovable_int extract_me(1);
|
||||
|
||||
if (!map1.extract(extract_me))
|
||||
return false;
|
||||
if (map1.extract(extract_me))
|
||||
return false;
|
||||
|
||||
if (!mmap1.extract(extract_me))
|
||||
return false;
|
||||
if (!mmap1.extract(extract_me))
|
||||
return false;
|
||||
if (mmap1.extract(extract_me))
|
||||
return false;
|
||||
}
|
||||
{
|
||||
typedef map<test::movable_int, char, less_transparent> map_t;
|
||||
|
||||
map_t map1;
|
||||
|
||||
//insert_or_assign
|
||||
if(!map1.insert_or_assign(1, 'e').second)
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
|
||||
//insert_or_assign with hint
|
||||
if(map1.find(2) != map1.end())
|
||||
return false;
|
||||
map_t::iterator i = map1.insert_or_assign(map1.begin(), 2, 'e');
|
||||
if(i != map1.insert_or_assign(map1.end(), 2, 'b'))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool constructor_template_auto_deduction_test()
|
||||
{
|
||||
|
||||
@@ -518,6 +390,7 @@ bool constructor_template_auto_deduction_test()
|
||||
|
||||
int main ()
|
||||
{
|
||||
using namespace boost::container::test;
|
||||
//Recursive container instantiation
|
||||
{
|
||||
map<recursive_map, recursive_map> map_;
|
||||
@@ -678,7 +551,15 @@ int main ()
|
||||
|
||||
test::test_merge_from_different_comparison();
|
||||
|
||||
if(!test::test_heterogeneous_lookups())
|
||||
if (!test::test_heterogeneous_lookup
|
||||
< map<int, char, less_transparent>
|
||||
, multimap<int, char, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
if (!test::test_heterogeneous_insert
|
||||
< map<test::movable_int, char, less_transparent>
|
||||
>())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
@@ -1542,6 +1542,165 @@ bool instantiate_constructors()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename IntMapType, typename IntMultimapType>
|
||||
bool test_heterogeneous_lookup()
|
||||
{
|
||||
{
|
||||
typedef IntMapType map_t;
|
||||
typedef IntMultimapType mmap_t;
|
||||
typedef typename map_t::value_type value_type;
|
||||
|
||||
map_t map1;
|
||||
const map_t &cmap1 = map1;
|
||||
|
||||
if(!map1.insert_or_assign(1, 'a').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(2, 'c').second)
|
||||
return false;
|
||||
if( map1.insert_or_assign(2, 'd').second)
|
||||
return false;
|
||||
if(!map1.insert_or_assign(3, 'e').second)
|
||||
return false;
|
||||
|
||||
mmap_t mmap1;
|
||||
const mmap_t &cmmap1 = mmap1;
|
||||
|
||||
mmap1.insert(value_type(1, 'a'));
|
||||
mmap1.insert(value_type(1, 'b'));
|
||||
mmap1.insert(value_type(2, 'c'));
|
||||
mmap1.insert(value_type(2, 'd'));
|
||||
mmap1.insert(value_type(3, 'e'));
|
||||
|
||||
const test::non_copymovable_int find_me(2);
|
||||
|
||||
//find
|
||||
if(map1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.find(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.find(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//count
|
||||
if(map1.count(find_me) != 1)
|
||||
return false;
|
||||
if(cmap1.count(find_me) != 1)
|
||||
return false;
|
||||
if(mmap1.count(find_me) != 2)
|
||||
return false;
|
||||
if(cmmap1.count(find_me) != 2)
|
||||
return false;
|
||||
|
||||
//contains
|
||||
if(!map1.contains(find_me))
|
||||
return false;
|
||||
if(!cmap1.contains(find_me))
|
||||
return false;
|
||||
if(!mmap1.contains(find_me))
|
||||
return false;
|
||||
if(!cmmap1.contains(find_me))
|
||||
return false;
|
||||
|
||||
//lower_bound
|
||||
if(map1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(cmap1.lower_bound(find_me)->second != 'd')
|
||||
return false;
|
||||
if(mmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.lower_bound(find_me)->second != 'c')
|
||||
return false;
|
||||
|
||||
//upper_bound
|
||||
if(map1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(mmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
if(cmmap1.upper_bound(find_me)->second != 'e')
|
||||
return false;
|
||||
|
||||
//equal_range
|
||||
if(map1.equal_range(find_me).first->second != 'd')
|
||||
return false;
|
||||
if(cmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
if(mmap1.equal_range(find_me).first->second != 'c')
|
||||
return false;
|
||||
if(cmmap1.equal_range(find_me).second->second != 'e')
|
||||
return false;
|
||||
|
||||
//erase
|
||||
if (map1.erase(find_me) != 1)
|
||||
return false;
|
||||
if (map1.erase(find_me) != 0)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 2)
|
||||
return false;
|
||||
if (mmap1.erase(find_me) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename MovableIntMapType>
|
||||
bool test_heterogeneous_insert()
|
||||
{
|
||||
{
|
||||
typedef MovableIntMapType map_t;
|
||||
|
||||
map_t map1;
|
||||
const map_t &cmap1 = map1;
|
||||
|
||||
//insert_or_assign
|
||||
if(!map1.insert_or_assign(1, 'e').second)
|
||||
return false;
|
||||
if (cmap1.find(1)->second != 'e')
|
||||
return false;
|
||||
if(map1.insert_or_assign(1, 'b').second)
|
||||
return false;
|
||||
if (cmap1.find(1)->second != 'b')
|
||||
return false;
|
||||
|
||||
//insert_or_assign with hint
|
||||
if(map1.find(2) != map1.end())
|
||||
return false;
|
||||
typename map_t::iterator i = map1.insert_or_assign(map1.begin(), 2, 'f');
|
||||
if(i != map1.insert_or_assign(map1.end(), 2, 'g'))
|
||||
return false;
|
||||
if (cmap1.find(2)->second != 'g')
|
||||
return false;
|
||||
|
||||
//try_emplace
|
||||
map1.clear();
|
||||
if(!map1.try_emplace(1, 'a').second)
|
||||
return false;
|
||||
if (cmap1.find(1)->second != 'a')
|
||||
return false;
|
||||
if( map1.try_emplace(1, 'b').second)
|
||||
return false;
|
||||
if (cmap1.find(1)->second != 'a')
|
||||
return false;
|
||||
|
||||
//try_emplace with hint
|
||||
i = map1.try_emplace(map1.end(), 2, 'c');
|
||||
if (cmap1.find(2)->second != 'c')
|
||||
return false;
|
||||
if (i != map1.try_emplace(map1.begin(), 2, 'd'))
|
||||
return false;
|
||||
if (cmap1.find(2)->second != 'c')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace test{
|
||||
} //namespace container {
|
||||
} //namespace boost{
|
||||
|
||||
Reference in New Issue
Block a user