bind_front_test.cc (6715B)
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 29 char CharAt(const char* s, size_t index) { return s[index]; } 30 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 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 { 46 std::string operator()() & { return "&"; } 47 std::string operator()() const& { return "const&"; } 48 std::string operator()() && { return "&&"; } 49 std::string operator()() const&& { return "const&&"; } 50 }; 51 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 { 62 std::string operator()(int&) const { return "&"; } // NOLINT 63 std::string operator()(const int&) const { return "const&"; } // NOLINT 64 std::string operator()(int&&) const { return "&&"; } 65 std::string operator()(const int&&) const { return "const&&"; } 66 }; 67 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; 81 const NonCopyableFunctor* operator()() const { return this; } 82 }; 83 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 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 { 108 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 115 const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; } 116 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 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 141 const std::string& GetNonCopyableValueByWrapper( 142 std::reference_wrapper<NonCopyable> n) { 143 return n.get().value; 144 } 145 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 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 168 int Sink(std::unique_ptr<int> p) { 169 return *p; 170 } 171 172 std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); } 173 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 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 { 189 FalseCopyable() {} 190 FalseCopyable(const FalseCopyable& other) : m(other.m) {} 191 FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {} 192 T m; 193 }; 194 195 int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; } 196 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 204 int Plus(int a, int b) { return a + b; } 205 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 static constexpr char data[] = "DEF"; 214 constexpr auto g = absl::bind_front(CharAt, data); 215 EXPECT_EQ(g(1), 'E'); 216 } 217 218 struct ManglingCall { 219 int operator()(int, double, std::string) const { return 0; } 220 }; 221 222 TEST(BindTest, Mangling) { 223 // We just want to generate a particular instantiation to see its mangling. 224 absl::bind_front(ManglingCall{}, 1, 3.3)("A"); 225 } 226 227 } // namespace