2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <folly/Partial.h>
20 #include <gtest/gtest.h>
24 int add3(int x, int y, int z) {
25 return 100 * x + 10 * y + z;
28 TEST(Partial, Simple) {
29 auto p0 = partial(&add3);
30 EXPECT_EQ(123, p0(1, 2, 3));
32 auto p1 = partial(&add3, 2);
33 EXPECT_EQ(234, p1(3, 4));
35 auto p2 = partial(&add3, 3, 4);
36 EXPECT_EQ(345, p2(5));
38 auto p3 = partial(&add3, 4, 5, 6);
43 int method(int& x, int& y, int& z) {
44 return 1000 + 100 * x + 10 * y + z;
46 int constMethod(int const& x, int const& y, int const& z) const {
47 return 2000 + 100 * x + 10 * y + z;
49 int tempMethod(int&& x, int&& y, int&& z) {
50 return 3000 + 100 * x + 10 * y + z;
54 TEST(Partial, ReferenceArguments) {
55 auto p0 = partial(&Foo::method, Foo{}, 2, 3);
57 EXPECT_EQ(1234, p0(four));
59 auto const p1 = partial(&Foo::constMethod, Foo{}, 3, 4);
60 EXPECT_EQ(2345, p1(5));
62 auto p2 = partial(&Foo::tempMethod, Foo{}, 4, 5);
63 EXPECT_EQ(3456, std::move(p2)(6));
66 struct RefQualifiers {
67 int operator()(int x, int y, int z) & {
68 return 1000 + 100 * x + 10 * y + z;
70 int operator()(int x, int y, int z) const& {
71 return 2000 + 100 * x + 10 * y + z;
73 int operator()(int x, int y, int z) && {
74 return 3000 + 100 * x + 10 * y + z;
78 TEST(Partial, RefQualifiers) {
79 auto p = partial(RefQualifiers{});
80 auto const& pconst = p;
82 EXPECT_EQ(1234, p(2, 3, 4));
83 EXPECT_EQ(2345, pconst(3, 4, 5));
84 EXPECT_EQ(3456, std::move(p)(4, 5, 6));
87 struct RefQualifiers2 {
88 int operator()(int& x, int const& y, int z) & {
89 return 1000 + 100 * x + 10 * y + z;
91 int operator()(int const& x, int y, int z) const& {
92 return 2000 + 100 * x + 10 * y + z;
94 int operator()(int&& x, int const& y, int z) && {
95 return 3000 + 100 * x + 10 * y + z;
99 TEST(Partial, RefQualifiers2) {
100 auto p = partial(RefQualifiers2{}, 9, 8);
101 auto const& pconst = p;
103 EXPECT_EQ(1984, p(4));
104 EXPECT_EQ(2985, pconst(5));
105 EXPECT_EQ(3986, std::move(p)(6));
108 std::unique_ptr<int> calc_uptr(std::unique_ptr<int> x, std::unique_ptr<int> y) {
109 *x = 100 * *x + 10 * *y;
113 TEST(Partial, MoveOnly) {
114 auto five = std::make_unique<int>(5);
115 auto six = std::make_unique<int>(6);
117 // create a partial object which holds a pointer to the `calc_uptr` function
118 // and a `unique_ptr<int>` for the first argument
119 auto p = partial(&calc_uptr, std::move(five));
121 // `five` should be moved out of
124 // call to the partial object as rvalue, which allows the call to consume
125 // captured data (here: the `unique_ptr<int>` storing 5), and pass it
126 // the other `unique_ptr`
127 auto result = std::move(p)(std::move(six));
129 // ...which now should be moved out of
132 EXPECT_EQ(560, *result);