Removed duplicate #includes
[folly.git] / folly / test / ApplyTupleTest.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <iostream>
18
19 #include "folly/ApplyTuple.h"
20 #include <gtest/gtest.h>
21
22 #include <memory>
23
24 namespace {
25
26 void func(int a, int b, double c) {
27   EXPECT_EQ(a, 1);
28   EXPECT_EQ(b, 2);
29   EXPECT_EQ(c, 3.0);
30 }
31
32 struct Wat {
33   void func(int a, int b, double c) {
34     ::func(a, b, c);
35   }
36
37   double retVal(int a, double b) {
38     return a + b;
39   }
40
41   Wat() {}
42   Wat(Wat const&) = delete;
43
44   int foo;
45 };
46
47 struct Overloaded {
48   int func(int) { return 0; }
49   bool func(bool) { return true; }
50 };
51
52 struct Func {
53   int operator()() const {
54     return 1;
55   }
56 };
57
58 struct CopyCount {
59   CopyCount() {}
60   CopyCount(CopyCount const&) {
61     std::cout << "copy count copy ctor\n";
62   }
63 };
64
65 void anotherFunc(CopyCount const&) {}
66
67 std::function<void (int, int, double)> makeFunc() {
68   return &func;
69 }
70
71 struct GuardObjBase {
72   GuardObjBase(GuardObjBase&&) {}
73   GuardObjBase() {}
74   GuardObjBase(GuardObjBase const&) = delete;
75   GuardObjBase& operator=(GuardObjBase const&) = delete;
76 };
77 typedef GuardObjBase const& Guard;
78
79 template<class F, class Tuple>
80 struct GuardObj : GuardObjBase {
81   explicit GuardObj(F&& f, Tuple&& args)
82     : f_(std::move(f))
83     , args_(std::move(args))
84   {}
85   GuardObj(GuardObj&& g)
86     : GuardObjBase(std::move(g))
87     , f_(std::move(g.f_))
88     , args_(std::move(g.args_))
89   {}
90
91   ~GuardObj() {
92     folly::applyTuple(f_, args_);
93   }
94
95   GuardObj(const GuardObj&) = delete;
96   GuardObj& operator=(const GuardObj&) = delete;
97
98 private:
99   F f_;
100   Tuple args_;
101 };
102
103 template<class F, class ...Args>
104 GuardObj<typename std::decay<F>::type,std::tuple<Args...>>
105 guard(F&& f, Args&&... args) {
106   return GuardObj<typename std::decay<F>::type,std::tuple<Args...>>(
107     std::forward<F>(f),
108     std::tuple<Args...>(std::forward<Args>(args)...)
109   );
110 }
111
112 struct Mover {
113   Mover() {}
114   Mover(Mover&&) {}
115   Mover(const Mover&) = delete;
116   Mover& operator=(const Mover&) = delete;
117 };
118
119 void move_only_func(Mover&&) {}
120
121 }
122
123 TEST(ApplyTuple, Test) {
124   auto argsTuple = std::make_tuple(1, 2, 3.0);
125   auto func2 = func;
126   folly::applyTuple(func2, argsTuple);
127   folly::applyTuple(func, argsTuple);
128   folly::applyTuple(func, std::make_tuple(1, 2, 3.0));
129   folly::applyTuple(makeFunc(), std::make_tuple(1, 2, 3.0));
130   folly::applyTuple(makeFunc(), argsTuple);
131
132   std::unique_ptr<Wat> wat(new Wat);
133   folly::applyTuple(&Wat::func, std::make_tuple(wat.get(), 1, 2, 3.0));
134   auto argsTuple2 = std::make_tuple(wat.get(), 1, 2, 3.0);
135   folly::applyTuple(&Wat::func, argsTuple2);
136
137   EXPECT_EQ(10.0,
138             folly::applyTuple(&Wat::retVal,
139                               std::make_tuple(wat.get(), 1, 9.0)));
140
141   auto test = guard(func, 1, 2, 3.0);
142   CopyCount cpy;
143   auto test2 = guard(anotherFunc, cpy);
144   auto test3 = guard(anotherFunc, std::cref(cpy));
145
146   Overloaded ovl;
147   EXPECT_EQ(0,
148             folly::applyTuple(
149               static_cast<int (Overloaded::*)(int)>(&Overloaded::func),
150               std::make_tuple(&ovl, 12)));
151   EXPECT_EQ(true,
152             folly::applyTuple(
153               static_cast<bool (Overloaded::*)(bool)>(&Overloaded::func),
154               std::make_tuple(&ovl, false)));
155
156   int x = folly::applyTuple(std::plus<int>(), std::make_tuple(12, 12));
157   EXPECT_EQ(24, x);
158
159   Mover m;
160   folly::applyTuple(move_only_func,
161                     std::forward_as_tuple(std::forward<Mover>(Mover())));
162 }