Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: base/bind_helpers.h

Issue 2106773002: Remove `Runnable` concept from base/bind_internal.h (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: +comment. fix spacing. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/bind.h ('k') | base/bind_internal.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This defines a set of argument wrappers and related factory methods that 5 // This defines a set of argument wrappers and related factory methods that
6 // can be used specify the refcounting and reference semantics of arguments 6 // can be used specify the refcounting and reference semantics of arguments
7 // that are bound by the Bind() function in base/bind.h. 7 // that are bound by the Bind() function in base/bind.h.
8 // 8 //
9 // It also defines a set of simple functions and utilities that people want 9 // It also defines a set of simple functions and utilities that people want
10 // when using Callback<> and Bind(). 10 // when using Callback<> and Bind().
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 #include "base/memory/weak_ptr.h" 169 #include "base/memory/weak_ptr.h"
170 #include "build/build_config.h" 170 #include "build/build_config.h"
171 171
172 namespace base { 172 namespace base {
173 173
174 template <typename T> 174 template <typename T>
175 struct IsWeakReceiver; 175 struct IsWeakReceiver;
176 176
177 namespace internal { 177 namespace internal {
178 178
179 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T
180 // for the existence of AddRef() and Release() functions of the correct
181 // signature.
182 //
183 // http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
184 // http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-templat e-to-check-for-a-functions-existence
185 // http://stackoverflow.com/questions/4358584/sfinae-approach-comparison
186 // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-memb er-functions
187 //
188 // The last link in particular show the method used below.
189 //
190 // For SFINAE to work with inherited methods, we need to pull some extra tricks
191 // with multiple inheritance. In the more standard formulation, the overloads
192 // of Check would be:
193 //
194 // template <typename C>
195 // Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*);
196 //
197 // template <typename C>
198 // No NotTheCheckWeWant(...);
199 //
200 // static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes);
201 //
202 // The problem here is that template resolution will not match
203 // C::TargetFunc if TargetFunc does not exist directly in C. That is, if
204 // TargetFunc in inherited from an ancestor, &C::TargetFunc will not match,
205 // |value| will be false. This formulation only checks for whether or
206 // not TargetFunc exist directly in the class being introspected.
207 //
208 // To get around this, we play a dirty trick with multiple inheritance.
209 // First, We create a class BaseMixin that declares each function that we
210 // want to probe for. Then we create a class Base that inherits from both T
211 // (the class we wish to probe) and BaseMixin. Note that the function
212 // signature in BaseMixin does not need to match the signature of the function
213 // we are probing for; thus it's easiest to just use void().
214 //
215 // Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
216 // ambiguous resolution between BaseMixin and T. This lets us write the
217 // following:
218 //
219 // template <typename C>
220 // No GoodCheck(Helper<&C::TargetFunc>*);
221 //
222 // template <typename C>
223 // Yes GoodCheck(...);
224 //
225 // static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes);
226 //
227 // Notice here that the variadic version of GoodCheck() returns Yes here
228 // instead of No like the previous one. Also notice that we calculate |value|
229 // by specializing GoodCheck() on Base instead of T.
230 //
231 // We've reversed the roles of the variadic, and Helper overloads.
232 // GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid
233 // substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve
234 // to the variadic version if T has TargetFunc. If T::TargetFunc does not
235 // exist, then &C::TargetFunc is not ambiguous, and the overload resolution
236 // will prefer GoodCheck(Helper<&C::TargetFunc>*).
237 //
238 // This method of SFINAE will correctly probe for inherited names, but it cannot
239 // typecheck those names. It's still a good enough sanity check though.
240 //
241 // Works on gcc-4.2, gcc-4.4, and Visual Studio 2008.
242 //
243
244 template <typename T>
245 class HasIsMethodTag {
246 using Yes = char[1];
247 using No = char[2];
248
249 template <typename U>
250 static Yes& Check(typename U::IsMethod*);
251
252 template <typename U>
253 static No& Check(...);
254
255 public:
256 enum { value = sizeof(Check<T>(0)) == sizeof(Yes) };
257 };
258
259 template <typename T> 179 template <typename T>
260 class UnretainedWrapper { 180 class UnretainedWrapper {
261 public: 181 public:
262 explicit UnretainedWrapper(T* o) : ptr_(o) {} 182 explicit UnretainedWrapper(T* o) : ptr_(o) {}
263 T* get() const { return ptr_; } 183 T* get() const { return ptr_; }
264 private: 184 private:
265 T* ptr_; 185 T* ptr_;
266 }; 186 };
267 187
268 template <typename T> 188 template <typename T>
(...skipping 11 matching lines...) Expand all
280 explicit RetainedRefWrapper(T* o) : ptr_(o) {} 200 explicit RetainedRefWrapper(T* o) : ptr_(o) {}
281 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {} 201 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
282 T* get() const { return ptr_.get(); } 202 T* get() const { return ptr_.get(); }
283 private: 203 private:
284 scoped_refptr<T> ptr_; 204 scoped_refptr<T> ptr_;
285 }; 205 };
286 206
287 template <typename T> 207 template <typename T>
288 struct IgnoreResultHelper { 208 struct IgnoreResultHelper {
289 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {} 209 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
210 explicit operator bool() const { return !!functor_; }
290 211
291 T functor_; 212 T functor_;
292 }; 213 };
293 214
294 // An alternate implementation is to avoid the destructive copy, and instead 215 // An alternate implementation is to avoid the destructive copy, and instead
295 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to 216 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
296 // a class that is essentially a std::unique_ptr<>. 217 // a class that is essentially a std::unique_ptr<>.
297 // 218 //
298 // The current implementation has the benefit though of leaving ParamTraits<> 219 // The current implementation has the benefit though of leaving ParamTraits<>
299 // fully in callback_internal.h as well as avoiding type conversions during 220 // fully in callback_internal.h as well as avoiding type conversions during
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 493
573 template <typename T> 494 template <typename T>
574 struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {}; 495 struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {};
575 496
576 template <typename T> 497 template <typename T>
577 struct IsWeakReceiver<WeakPtr<T>> : std::true_type {}; 498 struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
578 499
579 } // namespace base 500 } // namespace base
580 501
581 #endif // BASE_BIND_HELPERS_H_ 502 #endif // BASE_BIND_HELPERS_H_
OLDNEW
« no previous file with comments | « base/bind.h ('k') | base/bind_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698