• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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