1 // Copyright 2022 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/utility/utility.h"
16
17 #include <memory>
18 #include <sstream>
19 #include <string>
20 #include <tuple>
21 #include <type_traits>
22 #include <utility>
23 #include <vector>
24
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "absl/base/attributes.h"
28 #include "absl/memory/memory.h"
29 #include "absl/strings/str_cat.h"
30
31 namespace {
32
33 using ::testing::ElementsAre;
34 using ::testing::Pointee;
35 using ::testing::StaticAssertTypeEq;
36
37
Function(int a,int b)38 int Function(int a, int b) { return a - b; }
39
Sink(std::unique_ptr<int> p)40 int Sink(std::unique_ptr<int> p) { return *p; }
41
Factory(int n)42 std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
43
NoOp()44 void NoOp() {}
45
46 struct ConstFunctor {
operator ()__anon8355dc110111::ConstFunctor47 int operator()(int a, int b) const { return a - b; }
48 };
49
50 struct MutableFunctor {
operator ()__anon8355dc110111::MutableFunctor51 int operator()(int a, int b) { return a - b; }
52 };
53
54 struct EphemeralFunctor {
EphemeralFunctor__anon8355dc110111::EphemeralFunctor55 EphemeralFunctor() {}
EphemeralFunctor__anon8355dc110111::EphemeralFunctor56 EphemeralFunctor(const EphemeralFunctor&) {}
EphemeralFunctor__anon8355dc110111::EphemeralFunctor57 EphemeralFunctor(EphemeralFunctor&&) {}
operator ()__anon8355dc110111::EphemeralFunctor58 int operator()(int a, int b) && { return a - b; }
59 };
60
61 struct OverloadedFunctor {
OverloadedFunctor__anon8355dc110111::OverloadedFunctor62 OverloadedFunctor() {}
OverloadedFunctor__anon8355dc110111::OverloadedFunctor63 OverloadedFunctor(const OverloadedFunctor&) {}
OverloadedFunctor__anon8355dc110111::OverloadedFunctor64 OverloadedFunctor(OverloadedFunctor&&) {}
65 template <typename... Args>
operator ()__anon8355dc110111::OverloadedFunctor66 std::string operator()(const Args&... args) & {
67 return absl::StrCat("&", args...);
68 }
69 template <typename... Args>
operator ()__anon8355dc110111::OverloadedFunctor70 std::string operator()(const Args&... args) const& {
71 return absl::StrCat("const&", args...);
72 }
73 template <typename... Args>
operator ()__anon8355dc110111::OverloadedFunctor74 std::string operator()(const Args&... args) && {
75 return absl::StrCat("&&", args...);
76 }
77 };
78
79 struct Class {
Method__anon8355dc110111::Class80 int Method(int a, int b) { return a - b; }
ConstMethod__anon8355dc110111::Class81 int ConstMethod(int a, int b) const { return a - b; }
82
83 int member;
84 };
85
86 struct FlipFlop {
ConstMethod__anon8355dc110111::FlipFlop87 int ConstMethod() const { return member; }
operator *__anon8355dc110111::FlipFlop88 FlipFlop operator*() const { return {-member}; }
89
90 int member;
91 };
92
TEST(ApplyTest,Function)93 TEST(ApplyTest, Function) {
94 EXPECT_EQ(1, absl::apply(Function, std::make_tuple(3, 2)));
95 EXPECT_EQ(1, absl::apply(&Function, std::make_tuple(3, 2)));
96 }
97
TEST(ApplyTest,NonCopyableArgument)98 TEST(ApplyTest, NonCopyableArgument) {
99 EXPECT_EQ(42, absl::apply(Sink, std::make_tuple(absl::make_unique<int>(42))));
100 }
101
TEST(ApplyTest,NonCopyableResult)102 TEST(ApplyTest, NonCopyableResult) {
103 EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)), Pointee(42));
104 }
105
TEST(ApplyTest,VoidResult)106 TEST(ApplyTest, VoidResult) { absl::apply(NoOp, std::tuple<>()); }
107
TEST(ApplyTest,ConstFunctor)108 TEST(ApplyTest, ConstFunctor) {
109 EXPECT_EQ(1, absl::apply(ConstFunctor(), std::make_tuple(3, 2)));
110 }
111
TEST(ApplyTest,MutableFunctor)112 TEST(ApplyTest, MutableFunctor) {
113 MutableFunctor f;
114 EXPECT_EQ(1, absl::apply(f, std::make_tuple(3, 2)));
115 EXPECT_EQ(1, absl::apply(MutableFunctor(), std::make_tuple(3, 2)));
116 }
TEST(ApplyTest,EphemeralFunctor)117 TEST(ApplyTest, EphemeralFunctor) {
118 EphemeralFunctor f;
119 EXPECT_EQ(1, absl::apply(std::move(f), std::make_tuple(3, 2)));
120 EXPECT_EQ(1, absl::apply(EphemeralFunctor(), std::make_tuple(3, 2)));
121 }
TEST(ApplyTest,OverloadedFunctor)122 TEST(ApplyTest, OverloadedFunctor) {
123 OverloadedFunctor f;
124 const OverloadedFunctor& cf = f;
125
126 EXPECT_EQ("&", absl::apply(f, std::tuple<>{}));
127 EXPECT_EQ("& 42", absl::apply(f, std::make_tuple(" 42")));
128
129 EXPECT_EQ("const&", absl::apply(cf, std::tuple<>{}));
130 EXPECT_EQ("const& 42", absl::apply(cf, std::make_tuple(" 42")));
131
132 EXPECT_EQ("&&", absl::apply(std::move(f), std::tuple<>{}));
133 OverloadedFunctor f2;
134 EXPECT_EQ("&& 42", absl::apply(std::move(f2), std::make_tuple(" 42")));
135 }
136
TEST(ApplyTest,ReferenceWrapper)137 TEST(ApplyTest, ReferenceWrapper) {
138 ConstFunctor cf;
139 MutableFunctor mf;
140 EXPECT_EQ(1, absl::apply(std::cref(cf), std::make_tuple(3, 2)));
141 EXPECT_EQ(1, absl::apply(std::ref(cf), std::make_tuple(3, 2)));
142 EXPECT_EQ(1, absl::apply(std::ref(mf), std::make_tuple(3, 2)));
143 }
144
TEST(ApplyTest,MemberFunction)145 TEST(ApplyTest, MemberFunction) {
146 std::unique_ptr<Class> p(new Class);
147 std::unique_ptr<const Class> cp(new Class);
148 EXPECT_EQ(
149 1, absl::apply(&Class::Method,
150 std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2)));
151 EXPECT_EQ(1, absl::apply(&Class::Method,
152 std::tuple<Class*, int, int>(p.get(), 3, 2)));
153 EXPECT_EQ(
154 1, absl::apply(&Class::Method, std::tuple<Class&, int, int>(*p, 3, 2)));
155
156 EXPECT_EQ(
157 1, absl::apply(&Class::ConstMethod,
158 std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2)));
159 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
160 std::tuple<Class*, int, int>(p.get(), 3, 2)));
161 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
162 std::tuple<Class&, int, int>(*p, 3, 2)));
163
164 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
165 std::tuple<std::unique_ptr<const Class>&, int, int>(
166 cp, 3, 2)));
167 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
168 std::tuple<const Class*, int, int>(cp.get(), 3, 2)));
169 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
170 std::tuple<const Class&, int, int>(*cp, 3, 2)));
171
172 EXPECT_EQ(1, absl::apply(&Class::Method,
173 std::make_tuple(absl::make_unique<Class>(), 3, 2)));
174 EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
175 std::make_tuple(absl::make_unique<Class>(), 3, 2)));
176 EXPECT_EQ(
177 1, absl::apply(&Class::ConstMethod,
178 std::make_tuple(absl::make_unique<const Class>(), 3, 2)));
179 }
180
TEST(ApplyTest,DataMember)181 TEST(ApplyTest, DataMember) {
182 std::unique_ptr<Class> p(new Class{42});
183 std::unique_ptr<const Class> cp(new Class{42});
184 EXPECT_EQ(
185 42, absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)));
186 EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class&>(*p)));
187 EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class*>(p.get())));
188
189 absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)) = 42;
190 absl::apply(&Class::member, std::tuple<Class*>(p.get())) = 42;
191 absl::apply(&Class::member, std::tuple<Class&>(*p)) = 42;
192
193 EXPECT_EQ(42, absl::apply(&Class::member,
194 std::tuple<std::unique_ptr<const Class>&>(cp)));
195 EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<const Class&>(*cp)));
196 EXPECT_EQ(42,
197 absl::apply(&Class::member, std::tuple<const Class*>(cp.get())));
198 }
199
TEST(ApplyTest,FlipFlop)200 TEST(ApplyTest, FlipFlop) {
201 FlipFlop obj = {42};
202 // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
203 // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
204 EXPECT_EQ(42, absl::apply(&FlipFlop::ConstMethod, std::make_tuple(obj)));
205 EXPECT_EQ(42, absl::apply(&FlipFlop::member, std::make_tuple(obj)));
206 }
207
TEST(MakeFromTupleTest,String)208 TEST(MakeFromTupleTest, String) {
209 EXPECT_EQ(
210 absl::make_from_tuple<std::string>(std::make_tuple("hello world", 5)),
211 "hello");
212 }
213
TEST(MakeFromTupleTest,MoveOnlyParameter)214 TEST(MakeFromTupleTest, MoveOnlyParameter) {
215 struct S {
216 S(std::unique_ptr<int> n, std::unique_ptr<int> m) : value(*n + *m) {}
217 int value = 0;
218 };
219 auto tup =
220 std::make_tuple(absl::make_unique<int>(3), absl::make_unique<int>(4));
221 auto s = absl::make_from_tuple<S>(std::move(tup));
222 EXPECT_EQ(s.value, 7);
223 }
224
TEST(MakeFromTupleTest,NoParameters)225 TEST(MakeFromTupleTest, NoParameters) {
226 struct S {
227 S() : value(1) {}
228 int value = 2;
229 };
230 EXPECT_EQ(absl::make_from_tuple<S>(std::make_tuple()).value, 1);
231 }
232
TEST(MakeFromTupleTest,Pair)233 TEST(MakeFromTupleTest, Pair) {
234 EXPECT_EQ(
235 (absl::make_from_tuple<std::pair<bool, int>>(std::make_tuple(true, 17))),
236 std::make_pair(true, 17));
237 }
238
239 } // namespace
240