mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-30 03:17:15 +02:00
Better rvalue emulation support in extractors
Means that inserting rvalues into unordered_set/unordered_map won't create a node if no insert is required.
This commit is contained in:
@ -4267,6 +4267,11 @@ template <class ValueType> struct set_extractor
|
|||||||
|
|
||||||
static key_type const& extract(value_type const& v) { return v; }
|
static key_type const& extract(value_type const& v) { return v; }
|
||||||
|
|
||||||
|
static key_type const& extract(BOOST_UNORDERED_RV_REF(value_type) v)
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
static no_key extract() { return no_key(); }
|
static no_key extract() { return no_key(); }
|
||||||
|
|
||||||
template <class Arg> static no_key extract(Arg const&) { return no_key(); }
|
template <class Arg> static no_key extract(Arg const&) { return no_key(); }
|
||||||
@ -4306,6 +4311,22 @@ template <class ValueType> struct map_extractor
|
|||||||
return v.first;
|
return v.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
|
template <class Second>
|
||||||
|
static key_type const& extract(
|
||||||
|
boost::rv<std::pair<key_type, Second> > const& v)
|
||||||
|
{
|
||||||
|
return v.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Second>
|
||||||
|
static key_type const& extract(
|
||||||
|
boost::rv<std::pair<key_type const, Second> > const& v)
|
||||||
|
{
|
||||||
|
return v.first;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <class Arg1>
|
template <class Arg1>
|
||||||
static key_type const& extract(key_type const& k, Arg1 const&)
|
static key_type const& extract(key_type const& k, Arg1 const&)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +180,53 @@ template <class T> void unnecessary_copy_insert_test(T*)
|
|||||||
reset();
|
reset();
|
||||||
x.insert(a);
|
x.insert(a);
|
||||||
COPY_COUNT(1);
|
COPY_COUNT(1);
|
||||||
|
MOVE_COUNT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
|
||||||
|
{
|
||||||
|
T x;
|
||||||
|
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||||
|
reset();
|
||||||
|
x.insert(boost::move(a));
|
||||||
|
COPY_COUNT(0);
|
||||||
|
MOVE_COUNT(1);
|
||||||
|
|
||||||
|
BOOST_DEDUCED_TYPENAME T::value_type a2;
|
||||||
|
reset();
|
||||||
|
x.insert(boost::move(a));
|
||||||
|
COPY_COUNT(0);
|
||||||
|
MOVE_COUNT((x.size() == 2 ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
|
||||||
|
{
|
||||||
|
// Doesn't currently try to emulate std::pair move construction,
|
||||||
|
// so std::pair's require a copy. Could try emulating it in
|
||||||
|
// construct_from_args.
|
||||||
|
|
||||||
|
T x;
|
||||||
|
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||||
|
reset();
|
||||||
|
x.insert(boost::move(a));
|
||||||
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
|
COPY_COUNT(1);
|
||||||
|
MOVE_COUNT(0);
|
||||||
|
#else
|
||||||
|
COPY_COUNT(0);
|
||||||
|
MOVE_COUNT(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BOOST_DEDUCED_TYPENAME T::value_type a2;
|
||||||
|
reset();
|
||||||
|
x.insert(boost::move(a));
|
||||||
|
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||||
|
COPY_COUNT((x.size() == 2 ? 1 : 0));
|
||||||
|
MOVE_COUNT(0);
|
||||||
|
#else
|
||||||
|
COPY_COUNT(0);
|
||||||
|
MOVE_COUNT((x.size() == 2 ? 1 : 0));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::unordered_set<count_copies>* set;
|
boost::unordered_set<count_copies>* set;
|
||||||
@ -188,6 +235,8 @@ boost::unordered_map<int, count_copies>* map;
|
|||||||
boost::unordered_multimap<int, count_copies>* multimap;
|
boost::unordered_multimap<int, count_copies>* multimap;
|
||||||
|
|
||||||
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
|
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
|
||||||
|
UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset)))
|
||||||
|
UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap)))
|
||||||
|
|
||||||
template <class T> void unnecessary_copy_emplace_test(T*)
|
template <class T> void unnecessary_copy_emplace_test(T*)
|
||||||
{
|
{
|
||||||
@ -315,15 +364,10 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
|||||||
// the existing element.
|
// the existing element.
|
||||||
reset();
|
reset();
|
||||||
x.emplace();
|
x.emplace();
|
||||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
|
|
||||||
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
|
||||||
// source_cost doesn't make much sense here, but it seems to fit.
|
// source_cost doesn't make much sense here, but it seems to fit.
|
||||||
COPY_COUNT(1);
|
COPY_COUNT(1);
|
||||||
MOVE_COUNT(source_cost);
|
MOVE_COUNT(source_cost);
|
||||||
#else
|
|
||||||
COPY_COUNT(1);
|
|
||||||
MOVE_COUNT(1 + source_cost);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -347,13 +391,8 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
|
|||||||
// No move should take place.
|
// No move should take place.
|
||||||
reset();
|
reset();
|
||||||
x.emplace(boost::move(a));
|
x.emplace(boost::move(a));
|
||||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
|
||||||
COPY_COUNT(0);
|
COPY_COUNT(0);
|
||||||
MOVE_COUNT(0);
|
MOVE_COUNT(0);
|
||||||
#else
|
|
||||||
COPY_COUNT(0);
|
|
||||||
MOVE_COUNT(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use a new value for cases where a did get moved...
|
// Use a new value for cases where a did get moved...
|
||||||
count_copies b;
|
count_copies b;
|
||||||
|
Reference in New Issue
Block a user