Skip to content

Commit 35fdf0c

Browse files
author
Ryan Haining
committed
Adds support for move-only callables to groupby
Issue #89
1 parent f9f7de4 commit 35fdf0c

File tree

2 files changed

+67
-10
lines changed

2 files changed

+67
-10
lines changed

cppitertools/groupby.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class iter::impl::GroupProducer {
3535
using key_func_ret = std::invoke_result_t<KeyFunc, iterator_deref<T>>;
3636

3737
GroupProducer(Container&& container, KeyFunc key_func)
38-
: container_(std::forward<Container>(container)), key_func_(key_func) {}
38+
: container_(std::forward<Container>(container)),
39+
key_func_(std::move(key_func)) {}
3940

4041
public:
4142
GroupProducer(GroupProducer&&) = default;

test/test_groupby.cpp

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "helpers.hpp"
44

55
#include <iterator>
6+
#include <memory>
67
#include <string>
78
#include <vector>
89

@@ -21,37 +22,92 @@ namespace {
2122
}
2223
};
2324

25+
struct MoveOnlySizer {
26+
// here to trigger asan if a dangling reference gets used
27+
std::unique_ptr<int> counter_ = std::make_unique<int>();
28+
29+
MoveOnlySizer(const MoveOnlySizer&) = delete;
30+
MoveOnlySizer& operator=(const MoveOnlySizer&) = delete;
31+
32+
MoveOnlySizer(MoveOnlySizer&&) = default;
33+
MoveOnlySizer& operator=(MoveOnlySizer&&) = default;
34+
35+
int operator()(const std::string& s) {
36+
++*counter_;
37+
return s.size();
38+
}
39+
};
40+
2441
const std::vector<std::string> vec = {
2542
"hi", "ab", "ho", "abc", "def", "abcde", "efghi"};
2643
}
2744

28-
TEST_CASE("groupby: works with lambda, callable, and function pointer") {
45+
TEST_CASE("groupby: handles different callable types", "[groupby]") {
2946
std::vector<int> keys;
3047
std::vector<std::vector<std::string>> groups;
3148

32-
SECTION("Function pointer") {
33-
SECTION("Normal call") {
49+
SECTION("with function pointer") {
50+
SECTION("normal call") {
3451
for (auto&& gb : groupby(vec, length)) {
3552
keys.push_back(gb.first);
3653
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
3754
}
3855
}
39-
SECTION("Pipe") {
56+
SECTION("pipe") {
4057
for (auto&& gb : vec | groupby(length)) {
4158
keys.push_back(gb.first);
4259
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
4360
}
4461
}
4562
}
4663

47-
SECTION("Callable object") {
48-
for (auto&& gb : groupby(vec, Sizer{})) {
49-
keys.push_back(gb.first);
50-
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
64+
SECTION("with callable object") {
65+
SECTION("normal call") {
66+
for (auto&& gb : groupby(vec, Sizer{})) {
67+
keys.push_back(gb.first);
68+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
69+
}
70+
}
71+
SECTION("pipe") {
72+
for (auto&& gb : vec | groupby(Sizer{})) {
73+
keys.push_back(gb.first);
74+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
75+
}
5176
}
5277
}
5378

54-
SECTION("lambda function") {
79+
SECTION("with lvalue callable object") {
80+
auto sizer = Sizer{};
81+
SECTION("normal call") {
82+
for (auto&& gb : groupby(vec, sizer)) {
83+
keys.push_back(gb.first);
84+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
85+
}
86+
}
87+
SECTION("pipe") {
88+
for (auto&& gb : vec | groupby(sizer)) {
89+
keys.push_back(gb.first);
90+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
91+
}
92+
}
93+
}
94+
95+
SECTION("with move-only callable object") {
96+
SECTION("normal call") {
97+
for (auto&& gb : groupby(vec, MoveOnlySizer{})) {
98+
keys.push_back(gb.first);
99+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
100+
}
101+
}
102+
SECTION("pipe") {
103+
for (auto&& gb : vec | groupby(MoveOnlySizer{})) {
104+
keys.push_back(gb.first);
105+
groups.emplace_back(std::begin(gb.second), std::end(gb.second));
106+
}
107+
}
108+
}
109+
110+
SECTION("with lambda") {
55111
for (auto&& gb :
56112
groupby(vec, [](const std::string& s) { return s.size(); })) {
57113
keys.push_back(gb.first);

0 commit comments

Comments
 (0)