Skip to content

Commit 4b104c6

Browse files
authored
[libc++] Fix flat_{multi}set insert_range (#137462)
Fixes #136656
1 parent aec685e commit 4b104c6

File tree

3 files changed

+89
-1
lines changed

3 files changed

+89
-1
lines changed

libcxx/include/__flat_set/utils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP___FLAT_SET_UTILS_H
1212

1313
#include <__config>
14+
#include <__iterator/iterator_traits.h>
1415
#include <__ranges/access.h>
1516
#include <__ranges/concepts.h>
1617
#include <__type_traits/container_traits.h>
@@ -60,7 +61,8 @@ struct __flat_set_utils {
6061
// C++23 Sequence Container should have insert_range member function
6162
// Note that not all Sequence Containers provide append_range.
6263
__set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng));
63-
} else if constexpr (ranges::common_range<_Range>) {
64+
} else if constexpr (ranges::common_range<_Range> &&
65+
__has_input_iterator_category<ranges::iterator_t<_Range>>::value) {
6466
__set.__keys_.insert(__set.__keys_.end(), ranges::begin(__rng), ranges::end(__rng));
6567
} else {
6668
for (auto&& __x : __rng) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
// UNSUPPORTED: no-localization
11+
12+
// <flat_set>
13+
14+
// As an extension, libc++ flat containers support inserting a non forward range into
15+
// a pre-C++23 container that doesn't provide insert_range(...), since many containers
16+
// out there are in that situation.
17+
// https://github.com/llvm/llvm-project/issues/136656
18+
19+
#include <flat_set>
20+
#include <ranges>
21+
#include <sstream>
22+
#include <vector>
23+
24+
#include "MinSequenceContainer.h"
25+
#include "test_macros.h"
26+
27+
void test() {
28+
MinSequenceContainer<int> v;
29+
std::flat_multiset s(v);
30+
std::istringstream ints("0 1 1 0");
31+
auto r = std::ranges::subrange(std::istream_iterator<int>(ints), std::istream_iterator<int>()) |
32+
std::views::transform([](int i) { return i * i; });
33+
static_assert(
34+
![](auto& t) { return requires { t.insert_range(r); }; }(v),
35+
"This test is to test the case where the underlying container does not provide insert_range");
36+
s.insert_range(r);
37+
}
38+
39+
int main(int, char**) {
40+
test();
41+
42+
return 0;
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
// UNSUPPORTED: no-localization
11+
12+
// <flat_set>
13+
14+
// As an extension, libc++ flat containers support inserting a non forward range into
15+
// a pre-C++23 container that doesn't provide insert_range(...), since many containers
16+
// out there are in that situation.
17+
// https://github.com/llvm/llvm-project/issues/136656
18+
19+
#include <flat_set>
20+
#include <ranges>
21+
#include <sstream>
22+
#include <vector>
23+
24+
#include "MinSequenceContainer.h"
25+
#include "test_macros.h"
26+
27+
void test() {
28+
MinSequenceContainer<int> v;
29+
std::flat_set s(v);
30+
std::istringstream ints("0 1 1 0");
31+
auto r = std::ranges::subrange(std::istream_iterator<int>(ints), std::istream_iterator<int>()) |
32+
std::views::transform([](int i) { return i * i; });
33+
static_assert(
34+
![](auto& t) { return requires { t.insert_range(r); }; }(v),
35+
"This test is to test the case where the underlying container does not provide insert_range");
36+
s.insert_range(r);
37+
}
38+
39+
int main(int, char**) {
40+
test();
41+
42+
return 0;
43+
}

0 commit comments

Comments
 (0)