Implements LWG4121, "ranges::to constructs associative containers
via c.emplace(c.end(), *it)".
Using emplace_hint(it, arg) provides support for associative container
without from_range constructor, from which emplace(it, arg) constructrs
elements from it, arg. All statndard sequence containers that provides
emplace(it, arg) overload, provides push_back/emplace_back and are
handled by eariel branches.
libstdc++-v3/ChangeLog:
* include/std/ranges (ranges::to): Replace emplace(__c.end(), *__it)
with emplace_hint(__c.end(), *__it)
* testsuite/std/ranges/conv/1.cc: Update tests accordingly.
---
Testing on x86_64-linux. *ranges* test already passed in all
standard modes. OK for trunk when all test passes?
libstdc++-v3/include/std/ranges | 8 +--
libstdc++-v3/testsuite/std/ranges/conv/1.cc | 60 +++++++++++----------
2 files changed, 36 insertions(+), 32 deletions(-)
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 37f048e3d0d..5963647c378 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -9563,7 +9563,9 @@ namespace __detail
__c.reserve(static_cast<range_size_t<_Cont>>(ranges::size(__r)));
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 4016. container-insertable checks do not match what
- // container-inserter does
+ // container-inserter does
+ // 4121. ranges::to constructs associative containers
+ // via c.emplace(c.end(), *it)
auto __it = ranges::begin(__r);
const auto __sent = ranges::end(__r);
while (__it != __sent)
@@ -9572,8 +9574,8 @@ namespace __detail
__c.emplace_back(*__it);
else if constexpr (requires { __c.push_back(*__it); })
__c.push_back(*__it);
- else if constexpr (requires { __c.emplace(__c.end(), *__it);
})
- __c.emplace(__c.end(), *__it);
+ else if constexpr (requires { __c.emplace_hint(__c.end(),
*__it); })
+ __c.emplace_hint(__c.end(), *__it);
else
__c.insert(__c.end(), *__it);
++__it;
diff --git a/libstdc++-v3/testsuite/std/ranges/conv/1.cc
b/libstdc++-v3/testsuite/std/ranges/conv/1.cc
index 2caa1b83f30..14b52f6dd3c 100644
--- a/libstdc++-v3/testsuite/std/ranges/conv/1.cc
+++ b/libstdc++-v3/testsuite/std/ranges/conv/1.cc
@@ -9,6 +9,7 @@
#include <list>
#include <forward_list>
#include <map>
+#include <set>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
#include <testsuite_iterators.h>
@@ -204,13 +205,13 @@ test_2_1_3()
VERIFY( c2.c.get_allocator() == Alloc(78) );
}
-enum AppendKind { None, EmplaceBack, PushBack, Emplace, Insert };
+enum AppendKind { None, EmplaceBack, PushBack, EmplaceHint, Insert };
template<typename C, AppendKind Kind>
struct Cont4
{
// Only support construction with no args or an allocator.
- // This forces the use of either emplace_back, push_back, emplace or insert.
+ // This forces the use of either emplace_back, push_back, emplace_hint or
insert.
Cont4() { }
Cont4(typename C::allocator_type a) : c(a) { }
@@ -235,13 +236,13 @@ struct Cont4
}
template<typename T>
- requires (Kind <= Emplace)
- && requires(C& c, T&& t) { c.emplace(c.end(), std::forward<T>(t)); }
+ requires (Kind <= EmplaceHint)
+ && requires(C& c, T&& t) { c.emplace_hint(c.end(), std::forward<T>(t)); }
void
- emplace(typename C::iterator pos, T&& t)
+ emplace_hint(typename C::iterator pos, T&& t)
{
- kind = Emplace;
- c.emplace(pos, std::forward<T>(t));
+ kind = EmplaceHint;
+ c.emplace_hint(pos, std::forward<T>(t));
}
template<typename T>
@@ -287,6 +288,7 @@ test_2_1_4()
using Alloc2 = __gnu_test::uneq_allocator<short>;
using V = std::vector<int, Alloc>;
using List = std::list<short, Alloc2>;
+ using Set = std::set<int>;
std::list<unsigned> l{1u, 2u, 3u};
std::list<long> l2{4l, 5l, 6l};
@@ -337,30 +339,30 @@ test_2_1_4()
VERIFY( c6.kind == PushBack );
VERIFY( ! c6.used_reserve );
- // use vector::emplace and vector::reserve
- auto c7 = std::ranges::to<Cont4<V, Emplace>>(l);
- static_assert(std::is_same_v<decltype(c7), Cont4<V, Emplace>>);
- VERIFY( c7.c == V(l.begin(), l.end()) );
- VERIFY( c7.kind == Emplace );
- VERIFY( c7.used_reserve );
-
- // use vector::emplace and vector::reserve
- auto c8 = std::ranges::to<Cont4<V, Emplace>>(l2, Alloc(78));
- static_assert(std::is_same_v<decltype(c8), Cont4<V, Emplace>>);
- VERIFY( c8.c == V(l2.begin(), l2.end()) );
- VERIFY( c8.c.get_allocator() == Alloc(78) );
- VERIFY( c8.kind == Emplace );
- VERIFY( c8.used_reserve );
-
- // use list::emplace
- auto c9 = std::ranges::to<Cont4<List, Emplace>>(c.c, Alloc2(99));
- static_assert(std::is_same_v<decltype(c9), Cont4<List, Emplace>>);
- VERIFY( c9.c == List(l.begin(), l.end()) );
- VERIFY( c9.c.get_allocator() == Alloc(99) );
- VERIFY( c9.kind == Emplace );
+ // use list::emplace_back
+ auto c7 = std::ranges::to<Cont4<List, EmplaceBack>>(c.c, Alloc2(99));
+ static_assert(std::is_same_v<decltype(c7), Cont4<List, EmplaceBack>>);
+ VERIFY( c7.c == List(l.begin(), l.end()) );
+ VERIFY( c7.c.get_allocator() == Alloc(99) );
+ VERIFY( c7.kind == EmplaceBack );
+ VERIFY( ! c7.used_reserve );
+
+ // use set::emplace_hint
+ auto c8 = std::ranges::to<Cont4<Set, EmplaceHint>>(l);
+ static_assert(std::is_same_v<decltype(c8), Cont4<Set, EmplaceHint>>);
+ VERIFY( c8.c == Set(l.begin(), l.end()) );
+ VERIFY( c8.kind == EmplaceHint );
+ VERIFY( ! c8.used_reserve );
+
+ // use set::emplace_hint
+ auto c9 = std::ranges::to<Cont4<Set, EmplaceHint>>(l2, Alloc(78));
+ static_assert(std::is_same_v<decltype(c9), Cont4<Set, EmplaceHint>>);
+ VERIFY( c9.c == Set(l2.begin(), l2.end()) );
+ VERIFY( c9.c.get_allocator() == Alloc(78) );
+ VERIFY( c9.kind == EmplaceHint );
VERIFY( ! c9.used_reserve );
- // use vector::insert and vector::reserve
+ // use vector::insert and vector::reserve
auto c10 = std::ranges::to<Cont4<V, Insert>>(l);
static_assert(std::is_same_v<decltype(c10), Cont4<V, Insert>>);
VERIFY( c10.c == V(l.begin(), l.end()) );
--
2.55.0