1 // Copyright 2018 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/functional/bind_front.h"
16
17 #include <stddef.h>
18
19 #include <functional>
20 #include <memory>
21 #include <string>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/memory/memory.h"
26
27 namespace {
28
CharAt(const char * s,size_t index)29 char CharAt(const char* s, size_t index) { return s[index]; }
30
TEST(BindTest,Basics)31 TEST(BindTest, Basics) {
32 EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2));
33 EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2));
34 EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)());
35 }
36
TEST(BindTest,Lambda)37 TEST(BindTest, Lambda) {
38 auto lambda = [](int x, int y, int z) { return x + y + z; };
39 EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3));
40 EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3));
41 EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3));
42 EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)());
43 }
44
45 struct Functor {
operator ()__anon0645fb610111::Functor46 std::string operator()() & { return "&"; }
operator ()__anon0645fb610111::Functor47 std::string operator()() const& { return "const&"; }
operator ()__anon0645fb610111::Functor48 std::string operator()() && { return "&&"; }
operator ()__anon0645fb610111::Functor49 std::string operator()() const&& { return "const&&"; }
50 };
51
TEST(BindTest,PerfectForwardingOfBoundArgs)52 TEST(BindTest, PerfectForwardingOfBoundArgs) {
53 auto f = absl::bind_front(Functor());
54 const auto& cf = f;
55 EXPECT_EQ("&", f());
56 EXPECT_EQ("const&", cf());
57 EXPECT_EQ("&&", std::move(f)());
58 EXPECT_EQ("const&&", std::move(cf)());
59 }
60
61 struct ArgDescribe {
operator ()__anon0645fb610111::ArgDescribe62 std::string operator()(int&) const { return "&"; } // NOLINT
operator ()__anon0645fb610111::ArgDescribe63 std::string operator()(const int&) const { return "const&"; } // NOLINT
operator ()__anon0645fb610111::ArgDescribe64 std::string operator()(int&&) const { return "&&"; }
operator ()__anon0645fb610111::ArgDescribe65 std::string operator()(const int&&) const { return "const&&"; }
66 };
67
TEST(BindTest,PerfectForwardingOfFreeArgs)68 TEST(BindTest, PerfectForwardingOfFreeArgs) {
69 ArgDescribe f;
70 int i;
71 EXPECT_EQ("&", absl::bind_front(f)(static_cast<int&>(i)));
72 EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i)));
73 EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i)));
74 EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(i)));
75 }
76
77 struct NonCopyableFunctor {
78 NonCopyableFunctor() = default;
79 NonCopyableFunctor(const NonCopyableFunctor&) = delete;
80 NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete;
operator ()__anon0645fb610111::NonCopyableFunctor81 const NonCopyableFunctor* operator()() const { return this; }
82 };
83
TEST(BindTest,RefToFunctor)84 TEST(BindTest, RefToFunctor) {
85 // It won't copy/move the functor and use the original object.
86 NonCopyableFunctor ncf;
87 auto bound_ncf = absl::bind_front(std::ref(ncf));
88 auto bound_ncf_copy = bound_ncf;
89 EXPECT_EQ(&ncf, bound_ncf_copy());
90 }
91
92 struct Struct {
93 std::string value;
94 };
95
TEST(BindTest,StoreByCopy)96 TEST(BindTest, StoreByCopy) {
97 Struct s = {"hello"};
98 auto f = absl::bind_front(&Struct::value, s);
99 auto g = f;
100 EXPECT_EQ("hello", f());
101 EXPECT_EQ("hello", g());
102 EXPECT_NE(&s.value, &f());
103 EXPECT_NE(&s.value, &g());
104 EXPECT_NE(&g(), &f());
105 }
106
107 struct NonCopyable {
NonCopyable__anon0645fb610111::NonCopyable108 explicit NonCopyable(const std::string& s) : value(s) {}
109 NonCopyable(const NonCopyable&) = delete;
110 NonCopyable& operator=(const NonCopyable&) = delete;
111
112 std::string value;
113 };
114
GetNonCopyableValue(const NonCopyable & n)115 const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; }
116
TEST(BindTest,StoreByRef)117 TEST(BindTest, StoreByRef) {
118 NonCopyable s("hello");
119 auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s));
120 EXPECT_EQ("hello", f());
121 EXPECT_EQ(&s.value, &f());
122 auto g = std::move(f); // NOLINT
123 EXPECT_EQ("hello", g());
124 EXPECT_EQ(&s.value, &g());
125 s.value = "goodbye";
126 EXPECT_EQ("goodbye", g());
127 }
128
TEST(BindTest,StoreByCRef)129 TEST(BindTest, StoreByCRef) {
130 NonCopyable s("hello");
131 auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s));
132 EXPECT_EQ("hello", f());
133 EXPECT_EQ(&s.value, &f());
134 auto g = std::move(f); // NOLINT
135 EXPECT_EQ("hello", g());
136 EXPECT_EQ(&s.value, &g());
137 s.value = "goodbye";
138 EXPECT_EQ("goodbye", g());
139 }
140
GetNonCopyableValueByWrapper(std::reference_wrapper<NonCopyable> n)141 const std::string& GetNonCopyableValueByWrapper(
142 std::reference_wrapper<NonCopyable> n) {
143 return n.get().value;
144 }
145
TEST(BindTest,StoreByRefInvokeByWrapper)146 TEST(BindTest, StoreByRefInvokeByWrapper) {
147 NonCopyable s("hello");
148 auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s));
149 EXPECT_EQ("hello", f());
150 EXPECT_EQ(&s.value, &f());
151 auto g = std::move(f);
152 EXPECT_EQ("hello", g());
153 EXPECT_EQ(&s.value, &g());
154 s.value = "goodbye";
155 EXPECT_EQ("goodbye", g());
156 }
157
TEST(BindTest,StoreByPointer)158 TEST(BindTest, StoreByPointer) {
159 NonCopyable s("hello");
160 auto f = absl::bind_front(&NonCopyable::value, &s);
161 EXPECT_EQ("hello", f());
162 EXPECT_EQ(&s.value, &f());
163 auto g = std::move(f);
164 EXPECT_EQ("hello", g());
165 EXPECT_EQ(&s.value, &g());
166 }
167
Sink(std::unique_ptr<int> p)168 int Sink(std::unique_ptr<int> p) {
169 return *p;
170 }
171
Factory(int n)172 std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
173
TEST(BindTest,NonCopyableArg)174 TEST(BindTest, NonCopyableArg) {
175 EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));
176 EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))());
177 }
178
TEST(BindTest,NonCopyableResult)179 TEST(BindTest, NonCopyableResult) {
180 EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42));
181 EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42));
182 }
183
184 // is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to
185 // instantiate the copy constructor leads to a compile error. This is similar
186 // to how standard containers behave.
187 template <class T>
188 struct FalseCopyable {
FalseCopyable__anon0645fb610111::FalseCopyable189 FalseCopyable() {}
FalseCopyable__anon0645fb610111::FalseCopyable190 FalseCopyable(const FalseCopyable& other) : m(other.m) {}
FalseCopyable__anon0645fb610111::FalseCopyable191 FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}
192 T m;
193 };
194
GetMember(FalseCopyable<std::unique_ptr<int>> x)195 int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }
196
TEST(BindTest,WrappedMoveOnly)197 TEST(BindTest, WrappedMoveOnly) {
198 FalseCopyable<std::unique_ptr<int>> x;
199 x.m = absl::make_unique<int>(42);
200 auto f = absl::bind_front(&GetMember, std::move(x));
201 EXPECT_EQ(42, std::move(f)());
202 }
203
Plus(int a,int b)204 int Plus(int a, int b) { return a + b; }
205
TEST(BindTest,ConstExpr)206 TEST(BindTest, ConstExpr) {
207 constexpr auto f = absl::bind_front(CharAt);
208 EXPECT_EQ(f("ABC", 1), 'B');
209 static constexpr int five = 5;
210 constexpr auto plus5 = absl::bind_front(Plus, five);
211 EXPECT_EQ(plus5(1), 6);
212
213 // There seems to be a bug in MSVC dealing constexpr construction of
214 // char[]. Notice 'plus5' above; 'int' works just fine.
215 #if !(defined(_MSC_VER) && _MSC_VER < 1910)
216 static constexpr char data[] = "DEF";
217 constexpr auto g = absl::bind_front(CharAt, data);
218 EXPECT_EQ(g(1), 'E');
219 #endif
220 }
221
222 struct ManglingCall {
operator ()__anon0645fb610111::ManglingCall223 int operator()(int, double, std::string) const { return 0; }
224 };
225
TEST(BindTest,Mangling)226 TEST(BindTest, Mangling) {
227 // We just want to generate a particular instantiation to see its mangling.
228 absl::bind_front(ManglingCall{}, 1, 3.3)("A");
229 }
230
231 } // namespace
232