Skip to content

Commit 417b1eb

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

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

cppitertools/imap.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ namespace iter {
1616
// See #66
1717
-> StarMapper<MapFunc,
1818
decltype(zip(std::forward<Containers>(containers)...))> {
19-
return starmap(map_func, zip(std::forward<Containers>(containers)...));
19+
return starmap(
20+
std::move(map_func), zip(std::forward<Containers>(containers)...));
2021
}
2122
using PipeableAndBindFirst<IMapFn>::operator();
2223
};

test/test_imap.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,29 @@ namespace {
1717
return i + 1;
1818
}
1919

20-
class PlusOner {
20+
struct PlusOner {
21+
int operator()(int i) const {
22+
return i + 1;
23+
}
24+
};
25+
26+
class MoveOnlyAdder {
27+
private:
28+
// unique_ptr is better for triggering asan than an int if there's a
29+
// dangling reference to the callable
30+
std::unique_ptr<int> add_amount_;
31+
2132
public:
33+
MoveOnlyAdder(int v) : add_amount_{std::make_unique<int>(v)} {}
34+
35+
MoveOnlyAdder(const MoveOnlyAdder&) = delete;
36+
MoveOnlyAdder& operator=(const MoveOnlyAdder&) = delete;
37+
38+
MoveOnlyAdder(MoveOnlyAdder&&) = default;
39+
MoveOnlyAdder& operator=(MoveOnlyAdder&&) = default;
40+
2241
int operator()(int i) {
23-
return i + 1;
42+
return i + *add_amount_;
2443
}
2544
};
2645

@@ -33,31 +52,48 @@ namespace {
3352
}
3453
}
3554

36-
TEST_CASE("imap: works with lambda, callable, and function", "[imap]") {
37-
Vec ns = {10, 20, 30};
55+
TEST_CASE("imap: handles different callable types", "[imap]") {
56+
Vec ns = {10, 15, 300};
57+
Vec vc = {11, 16, 301};
3858
std::vector<int> v;
39-
SECTION("with lambda") {
40-
auto im = imap([](int i) { return i + 1; }, ns);
41-
v.assign(std::begin(im), std::end(im));
59+
SECTION("with function pointer") {
60+
auto m = imap(plusone, ns);
61+
v = Vec(std::begin(m), std::end(m));
4262
}
4363

44-
SECTION("with callable") {
45-
SECTION("Normal call") {
46-
auto im = imap(PlusOner{}, ns);
47-
v.assign(std::begin(im), std::end(im));
64+
SECTION("with callable object") {
65+
auto m = imap(PlusOner{}, ns);
66+
v = Vec(std::begin(m), std::end(m));
67+
}
68+
69+
SECTION("with lvalue callable object") {
70+
auto lt = PlusOner{};
71+
SECTION("normal call") {
72+
auto m = imap(lt, ns);
73+
v = Vec(std::begin(m), std::end(m));
4874
}
49-
SECTION("Pipe") {
50-
auto im = ns | imap(PlusOner{});
51-
v.assign(std::begin(im), std::end(im));
75+
SECTION("pipe") {
76+
auto m = ns | imap(lt);
77+
v = Vec(std::begin(m), std::end(m));
5278
}
5379
}
5480

55-
SECTION("with function") {
56-
auto im = imap(PlusOner{}, ns);
57-
v.assign(std::begin(im), std::end(im));
81+
SECTION("with move-only callable object") {
82+
SECTION("normal call") {
83+
auto m = imap(MoveOnlyAdder{1}, ns);
84+
v = Vec(std::begin(m), std::end(m));
85+
}
86+
SECTION("pipe") {
87+
auto m = ns | imap(MoveOnlyAdder{1});
88+
v = Vec(std::begin(m), std::end(m));
89+
}
5890
}
5991

60-
Vec vc = {11, 21, 31};
92+
SECTION("with lambda") {
93+
auto ltf = [](int i) { return i + 1; };
94+
auto m = imap(ltf, ns);
95+
v = Vec(std::begin(m), std::end(m));
96+
}
6197
REQUIRE(v == vc);
6298
}
6399

0 commit comments

Comments
 (0)