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