Tony Mak | 336fd9e | 2020-10-27 17:04:20 +0000 | [diff] [blame^] | 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 | // ----------------------------------------------------------------------------- |
| 16 | // File: bind_front.h |
| 17 | // ----------------------------------------------------------------------------- |
| 18 | // |
| 19 | // `absl::bind_front()` returns a functor by binding a number of arguments to |
| 20 | // the front of a provided (usually more generic) functor. Unlike `std::bind`, |
| 21 | // it does not require the use of argument placeholders. The simpler syntax of |
| 22 | // `absl::bind_front()` allows you to avoid known misuses with `std::bind()`. |
| 23 | // |
| 24 | // `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming |
| 25 | // `std::bind_front()`, which similarly resolves these issues with |
| 26 | // `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow |
| 27 | // partial function application. (See |
| 28 | // https://en.wikipedia.org/wiki/Partial_application). |
| 29 | |
| 30 | #ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_ |
| 31 | #define ABSL_FUNCTIONAL_BIND_FRONT_H_ |
| 32 | |
| 33 | #include "absl/functional/internal/front_binder.h" |
| 34 | #include "absl/utility/utility.h" |
| 35 | |
| 36 | namespace absl { |
| 37 | ABSL_NAMESPACE_BEGIN |
| 38 | |
| 39 | // bind_front() |
| 40 | // |
| 41 | // Binds the first N arguments of an invocable object and stores them by value. |
| 42 | // |
| 43 | // Like `std::bind()`, `absl::bind_front()` is implicitly convertible to |
| 44 | // `std::function`. In particular, it may be used as a simpler replacement for |
| 45 | // `std::bind()` in most cases, as it does not require placeholders to be |
| 46 | // specified. More importantly, it provides more reliable correctness guarantees |
| 47 | // than `std::bind()`; while `std::bind()` will silently ignore passing more |
| 48 | // parameters than expected, for example, `absl::bind_front()` will report such |
| 49 | // mis-uses as errors. |
| 50 | // |
| 51 | // absl::bind_front(a...) can be seen as storing the results of |
| 52 | // std::make_tuple(a...). |
| 53 | // |
| 54 | // Example: Binding a free function. |
| 55 | // |
| 56 | // int Minus(int a, int b) { return a - b; } |
| 57 | // |
| 58 | // assert(absl::bind_front(Minus)(3, 2) == 3 - 2); |
| 59 | // assert(absl::bind_front(Minus, 3)(2) == 3 - 2); |
| 60 | // assert(absl::bind_front(Minus, 3, 2)() == 3 - 2); |
| 61 | // |
| 62 | // Example: Binding a member function. |
| 63 | // |
| 64 | // struct Math { |
| 65 | // int Double(int a) const { return 2 * a; } |
| 66 | // }; |
| 67 | // |
| 68 | // Math math; |
| 69 | // |
| 70 | // assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3); |
| 71 | // // Stores a pointer to math inside the functor. |
| 72 | // assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3); |
| 73 | // // Stores a copy of math inside the functor. |
| 74 | // assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3); |
| 75 | // // Stores std::unique_ptr<Math> inside the functor. |
| 76 | // assert(absl::bind_front(&Math::Double, |
| 77 | // std::unique_ptr<Math>(new Math))(3) == 2 * 3); |
| 78 | // |
| 79 | // Example: Using `absl::bind_front()`, instead of `std::bind()`, with |
| 80 | // `std::function`. |
| 81 | // |
| 82 | // class FileReader { |
| 83 | // public: |
| 84 | // void ReadFileAsync(const std::string& filename, std::string* content, |
| 85 | // const std::function<void()>& done) { |
| 86 | // // Calls Executor::Schedule(std::function<void()>). |
| 87 | // Executor::DefaultExecutor()->Schedule( |
| 88 | // absl::bind_front(&FileReader::BlockingRead, this, |
| 89 | // filename, content, done)); |
| 90 | // } |
| 91 | // |
| 92 | // private: |
| 93 | // void BlockingRead(const std::string& filename, std::string* content, |
| 94 | // const std::function<void()>& done) { |
| 95 | // CHECK_OK(file::GetContents(filename, content, {})); |
| 96 | // done(); |
| 97 | // } |
| 98 | // }; |
| 99 | // |
| 100 | // `absl::bind_front()` stores bound arguments explicitly using the type passed |
| 101 | // rather than implicitly based on the type accepted by its functor. |
| 102 | // |
| 103 | // Example: Binding arguments explicitly. |
| 104 | // |
| 105 | // void LogStringView(absl::string_view sv) { |
| 106 | // LOG(INFO) << sv; |
| 107 | // } |
| 108 | // |
| 109 | // Executor* e = Executor::DefaultExecutor(); |
| 110 | // std::string s = "hello"; |
| 111 | // absl::string_view sv = s; |
| 112 | // |
| 113 | // // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it. |
| 114 | // e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling |
| 115 | // // string_view. |
| 116 | // |
| 117 | // e->Schedule(absl::bind_front(LogStringView, s)); // OK: stores a copy of |
| 118 | // // s. |
| 119 | // |
| 120 | // To store some of the arguments passed to `absl::bind_front()` by reference, |
| 121 | // use std::ref()` and `std::cref()`. |
| 122 | // |
| 123 | // Example: Storing some of the bound arguments by reference. |
| 124 | // |
| 125 | // class Service { |
| 126 | // public: |
| 127 | // void Serve(const Request& req, std::function<void()>* done) { |
| 128 | // // The request protocol buffer won't be deleted until done is called. |
| 129 | // // It's safe to store a reference to it inside the functor. |
| 130 | // Executor::DefaultExecutor()->Schedule( |
| 131 | // absl::bind_front(&Service::BlockingServe, this, std::cref(req), |
| 132 | // done)); |
| 133 | // } |
| 134 | // |
| 135 | // private: |
| 136 | // void BlockingServe(const Request& req, std::function<void()>* done); |
| 137 | // }; |
| 138 | // |
| 139 | // Example: Storing bound arguments by reference. |
| 140 | // |
| 141 | // void Print(const std::string& a, const std::string& b) { |
| 142 | // std::cerr << a << b; |
| 143 | // } |
| 144 | // |
| 145 | // std::string hi = "Hello, "; |
| 146 | // std::vector<std::string> names = {"Chuk", "Gek"}; |
| 147 | // // Doesn't copy hi. |
| 148 | // for_each(names.begin(), names.end(), |
| 149 | // absl::bind_front(Print, std::ref(hi))); |
| 150 | // |
| 151 | // // DO NOT DO THIS: the functor may outlive "hi", resulting in |
| 152 | // // dangling references. |
| 153 | // foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest")); // BAD! |
| 154 | // auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD! |
| 155 | // |
| 156 | // Example: Storing reference-like types. |
| 157 | // |
| 158 | // void Print(absl::string_view a, const std::string& b) { |
| 159 | // std::cerr << a << b; |
| 160 | // } |
| 161 | // |
| 162 | // std::string hi = "Hello, "; |
| 163 | // // Copies "hi". |
| 164 | // absl::bind_front(Print, hi)("Chuk"); |
| 165 | // |
| 166 | // // Compile error: std::reference_wrapper<const string> is not implicitly |
| 167 | // // convertible to string_view. |
| 168 | // // absl::bind_front(Print, std::cref(hi))("Chuk"); |
| 169 | // |
| 170 | // // Doesn't copy "hi". |
| 171 | // absl::bind_front(Print, absl::string_view(hi))("Chuk"); |
| 172 | // |
| 173 | template <class F, class... BoundArgs> |
| 174 | constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front( |
| 175 | F&& func, BoundArgs&&... args) { |
| 176 | return functional_internal::bind_front_t<F, BoundArgs...>( |
| 177 | absl::in_place, absl::forward<F>(func), |
| 178 | absl::forward<BoundArgs>(args)...); |
| 179 | } |
| 180 | |
| 181 | ABSL_NAMESPACE_END |
| 182 | } // namespace absl |
| 183 | |
| 184 | #endif // ABSL_FUNCTIONAL_BIND_FRONT_H_ |