bind_front_test.cc 6.7 KB

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