You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							277 lines
						
					
					
						
							9.0 KiB
						
					
					
				
			
		
		
	
	
							277 lines
						
					
					
						
							9.0 KiB
						
					
					
				| // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
 | |
| // Licensed under the MIT License:
 | |
| //
 | |
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| // of this software and associated documentation files (the "Software"), to deal
 | |
| // in the Software without restriction, including without limitation the rights
 | |
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| // copies of the Software, and to permit persons to whom the Software is
 | |
| // furnished to do so, subject to the following conditions:
 | |
| //
 | |
| // The above copyright notice and this permission notice shall be included in
 | |
| // all copies or substantial portions of the Software.
 | |
| //
 | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
| // THE SOFTWARE.
 | |
| 
 | |
| #ifndef KJ_FUNCTION_H_
 | |
| #define KJ_FUNCTION_H_
 | |
| 
 | |
| #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
 | |
| #pragma GCC system_header
 | |
| #endif
 | |
| 
 | |
| #include "memory.h"
 | |
| 
 | |
| namespace kj {
 | |
| 
 | |
| template <typename Signature>
 | |
| class Function;
 | |
| // Function wrapper using virtual-based polymorphism.  Use this when template polymorphism is
 | |
| // not possible.  You can, for example, accept a Function as a parameter:
 | |
| //
 | |
| //     void setFilter(Function<bool(const Widget&)> filter);
 | |
| //
 | |
| // The caller of `setFilter()` may then pass any callable object as the parameter.  The callable
 | |
| // object does not have to have the exact signature specified, just one that is "compatible" --
 | |
| // i.e. the return type is covariant and the parameters are contravariant.
 | |
| //
 | |
| // Unlike `std::function`, `kj::Function`s are movable but not copyable, just like `kj::Own`.  This
 | |
| // is to avoid unexpected heap allocation or slow atomic reference counting.
 | |
| //
 | |
| // When a `Function` is constructed from an lvalue, it captures only a reference to the value.
 | |
| // When constructed from an rvalue, it invokes the value's move constructor.  So, for example:
 | |
| //
 | |
| //     struct AddN {
 | |
| //       int n;
 | |
| //       int operator(int i) { return i + n; }
 | |
| //     }
 | |
| //
 | |
| //     Function<int(int, int)> f1 = AddN{2};
 | |
| //     // f1 owns an instance of AddN.  It may safely be moved out
 | |
| //     // of the local scope.
 | |
| //
 | |
| //     AddN adder(2);
 | |
| //     Function<int(int, int)> f2 = adder;
 | |
| //     // f2 contains a reference to `adder`.  Thus, it becomes invalid
 | |
| //     // when `adder` goes out-of-scope.
 | |
| //
 | |
| //     AddN adder2(2);
 | |
| //     Function<int(int, int)> f3 = kj::mv(adder2);
 | |
| //     // f3 owns an insatnce of AddN moved from `adder2`.  f3 may safely
 | |
| //     // be moved out of the local scope.
 | |
| //
 | |
| // Additionally, a Function may be bound to a class method using KJ_BIND_METHOD(object, methodName).
 | |
| // For example:
 | |
| //
 | |
| //     class Printer {
 | |
| //     public:
 | |
| //       void print(int i);
 | |
| //       void print(kj::StringPtr s);
 | |
| //     };
 | |
| //
 | |
| //     Printer p;
 | |
| //
 | |
| //     Function<void(uint)> intPrinter = KJ_BIND_METHOD(p, print);
 | |
| //     // Will call Printer::print(int).
 | |
| //
 | |
| //     Function<void(const char*)> strPrinter = KJ_BIND_METHOD(p, print);
 | |
| //     // Will call Printer::print(kj::StringPtr).
 | |
| //
 | |
| // Notice how KJ_BIND_METHOD is able to figure out which overload to use depending on the kind of
 | |
| // Function it is binding to.
 | |
| 
 | |
| template <typename Signature>
 | |
| class ConstFunction;
 | |
| // Like Function, but wraps a "const" (i.e. thread-safe) call.
 | |
| 
 | |
| template <typename Return, typename... Params>
 | |
| class Function<Return(Params...)> {
 | |
| public:
 | |
|   template <typename F>
 | |
|   inline Function(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
 | |
|   Function() = default;
 | |
| 
 | |
|   // Make sure people don't accidentally end up wrapping a reference when they meant to return
 | |
|   // a function.
 | |
|   KJ_DISALLOW_COPY(Function);
 | |
|   Function(Function&) = delete;
 | |
|   Function& operator=(Function&) = delete;
 | |
|   template <typename T> Function(const Function<T>&) = delete;
 | |
|   template <typename T> Function& operator=(const Function<T>&) = delete;
 | |
|   template <typename T> Function(const ConstFunction<T>&) = delete;
 | |
|   template <typename T> Function& operator=(const ConstFunction<T>&) = delete;
 | |
|   Function(Function&&) = default;
 | |
|   Function& operator=(Function&&) = default;
 | |
| 
 | |
|   inline Return operator()(Params... params) {
 | |
|     return (*impl)(kj::fwd<Params>(params)...);
 | |
|   }
 | |
| 
 | |
|   Function reference() {
 | |
|     // Forms a new Function of the same type that delegates to this Function by reference.
 | |
|     // Therefore, this Function must outlive the returned Function, but otherwise they behave
 | |
|     // exactly the same.
 | |
| 
 | |
|     return *impl;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   class Iface {
 | |
|   public:
 | |
|     virtual Return operator()(Params... params) = 0;
 | |
|   };
 | |
| 
 | |
|   template <typename F>
 | |
|   class Impl final: public Iface {
 | |
|   public:
 | |
|     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
 | |
| 
 | |
|     Return operator()(Params... params) override {
 | |
|       return f(kj::fwd<Params>(params)...);
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     F f;
 | |
|   };
 | |
| 
 | |
|   Own<Iface> impl;
 | |
| };
 | |
| 
 | |
| template <typename Return, typename... Params>
 | |
| class ConstFunction<Return(Params...)> {
 | |
| public:
 | |
|   template <typename F>
 | |
|   inline ConstFunction(F&& f): impl(heap<Impl<F>>(kj::fwd<F>(f))) {}
 | |
|   ConstFunction() = default;
 | |
| 
 | |
|   // Make sure people don't accidentally end up wrapping a reference when they meant to return
 | |
|   // a function.
 | |
|   KJ_DISALLOW_COPY(ConstFunction);
 | |
|   ConstFunction(ConstFunction&) = delete;
 | |
|   ConstFunction& operator=(ConstFunction&) = delete;
 | |
|   template <typename T> ConstFunction(const ConstFunction<T>&) = delete;
 | |
|   template <typename T> ConstFunction& operator=(const ConstFunction<T>&) = delete;
 | |
|   template <typename T> ConstFunction(const Function<T>&) = delete;
 | |
|   template <typename T> ConstFunction& operator=(const Function<T>&) = delete;
 | |
|   ConstFunction(ConstFunction&&) = default;
 | |
|   ConstFunction& operator=(ConstFunction&&) = default;
 | |
| 
 | |
|   inline Return operator()(Params... params) const {
 | |
|     return (*impl)(kj::fwd<Params>(params)...);
 | |
|   }
 | |
| 
 | |
|   ConstFunction reference() const {
 | |
|     // Forms a new ConstFunction of the same type that delegates to this ConstFunction by reference.
 | |
|     // Therefore, this ConstFunction must outlive the returned ConstFunction, but otherwise they
 | |
|     // behave exactly the same.
 | |
| 
 | |
|     return *impl;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   class Iface {
 | |
|   public:
 | |
|     virtual Return operator()(Params... params) const = 0;
 | |
|   };
 | |
| 
 | |
|   template <typename F>
 | |
|   class Impl final: public Iface {
 | |
|   public:
 | |
|     explicit Impl(F&& f): f(kj::fwd<F>(f)) {}
 | |
| 
 | |
|     Return operator()(Params... params) const override {
 | |
|       return f(kj::fwd<Params>(params)...);
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     F f;
 | |
|   };
 | |
| 
 | |
|   Own<Iface> impl;
 | |
| };
 | |
| 
 | |
| #if 1
 | |
| 
 | |
| namespace _ {  // private
 | |
| 
 | |
| template <typename T, typename Signature, Signature method>
 | |
| class BoundMethod;
 | |
| 
 | |
| template <typename T, typename Return, typename... Params, Return (Decay<T>::*method)(Params...)>
 | |
| class BoundMethod<T, Return (Decay<T>::*)(Params...), method> {
 | |
| public:
 | |
|   BoundMethod(T&& t): t(kj::fwd<T>(t)) {}
 | |
| 
 | |
|   Return operator()(Params&&... params) {
 | |
|     return (t.*method)(kj::fwd<Params>(params)...);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   T t;
 | |
| };
 | |
| 
 | |
| template <typename T, typename Return, typename... Params,
 | |
|           Return (Decay<T>::*method)(Params...) const>
 | |
| class BoundMethod<T, Return (Decay<T>::*)(Params...) const, method> {
 | |
| public:
 | |
|   BoundMethod(T&& t): t(kj::fwd<T>(t)) {}
 | |
| 
 | |
|   Return operator()(Params&&... params) const {
 | |
|     return (t.*method)(kj::fwd<Params>(params)...);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   T t;
 | |
| };
 | |
| 
 | |
| }  // namespace _ (private)
 | |
| 
 | |
| #define KJ_BIND_METHOD(obj, method) \
 | |
|   ::kj::_::BoundMethod<KJ_DECLTYPE_REF(obj), \
 | |
|                        decltype(&::kj::Decay<decltype(obj)>::method), \
 | |
|                        &::kj::Decay<decltype(obj)>::method>(obj)
 | |
| // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
 | |
| // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
 | |
| // contain a copy (by move) of it.
 | |
| //
 | |
| // The current implementation requires that the method is not overloaded.
 | |
| //
 | |
| // TODO(someday):  C++14's generic lambdas may be able to simplify this code considerably, and
 | |
| //   probably make it work with overloaded methods.
 | |
| 
 | |
| #else
 | |
| // Here's a better implementation of the above that doesn't work with GCC (but does with Clang)
 | |
| // because it uses a local class with a template method.  Sigh.  This implementation supports
 | |
| // overloaded methods.
 | |
| 
 | |
| #define KJ_BIND_METHOD(obj, method) \
 | |
|   ({ \
 | |
|     typedef KJ_DECLTYPE_REF(obj) T; \
 | |
|     class F { \
 | |
|     public: \
 | |
|       inline F(T&& t): t(::kj::fwd<T>(t)) {} \
 | |
|       template <typename... Params> \
 | |
|       auto operator()(Params&&... params) \
 | |
|           -> decltype(::kj::instance<T>().method(::kj::fwd<Params>(params)...)) { \
 | |
|         return t.method(::kj::fwd<Params>(params)...); \
 | |
|       } \
 | |
|     private: \
 | |
|       T t; \
 | |
|     }; \
 | |
|     (F(obj)); \
 | |
|   })
 | |
| // Macro that produces a functor object which forwards to the method `obj.name`.  If `obj` is an
 | |
| // lvalue, the functor will hold a reference to it.  If `obj` is an rvalue, the functor will
 | |
| // contain a copy (by move) of it.
 | |
| 
 | |
| #endif
 | |
| 
 | |
| }  // namespace kj
 | |
| 
 | |
| #endif  // KJ_FUNCTION_H_
 | |
| 
 |