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