1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkFunction_DEFINED 9 #define SkFunction_DEFINED 10 11 // TODO: document, more pervasive move support in constructors, small-Fn optimization 12 13 #include "SkTemplates.h" 14 #include "SkTypes.h" 15 16 template <typename> class SkFunction; 17 18 template <typename R, typename... Args> 19 class SkFunction<R(Args...)> { 20 public: SkFunction()21 SkFunction() {} 22 23 template <typename Fn> SkFunction(const Fn & fn)24 SkFunction(const Fn& fn) : fFunction(SkNEW_ARGS(LambdaImpl<Fn>, (fn))) {} 25 SkFunction(R (* fn)(Args...))26 SkFunction(R (*fn)(Args...)) : fFunction(SkNEW_ARGS(FnPtrImpl, (fn))) {} 27 SkFunction(const SkFunction & other)28 SkFunction(const SkFunction& other) { *this = other; } 29 SkFunction& operator=(const SkFunction& other) { 30 if (this != &other) { 31 fFunction.reset(other.fFunction ? other.fFunction->clone() : nullptr); 32 } 33 return *this; 34 } 35 operator()36 R operator()(Args... args) const { 37 SkASSERT(fFunction.get()); 38 return fFunction->call(Forward(args)...); 39 } 40 41 private: 42 // ~= std::forward. This moves its argument if possible, falling back to a copy if not. Forward(T & v)43 template <typename T> static T&& Forward(T& v) { return (T&&)v; } 44 45 struct Interface { ~InterfaceInterface46 virtual ~Interface() {} 47 virtual R call(Args...) const = 0; 48 virtual Interface* clone() const = 0; 49 }; 50 51 template <typename Fn> 52 class LambdaImpl final : public Interface { 53 public: LambdaImpl(const Fn & fn)54 LambdaImpl(const Fn& fn) : fFn(fn) {} 55 call(Args...args)56 R call(Args... args) const override { return fFn(Forward(args)...); } clone()57 Interface* clone() const { return SkNEW_ARGS(LambdaImpl<Fn>, (fFn)); } 58 private: 59 Fn fFn; 60 }; 61 62 class FnPtrImpl final : public Interface { 63 public: FnPtrImpl(R (* fn)(Args...))64 FnPtrImpl(R (*fn)(Args...)) : fFn(fn) {} 65 call(Args...args)66 R call(Args... args) const override { return fFn(Forward(args)...); } clone()67 Interface* clone() const { return SkNEW_ARGS(FnPtrImpl, (fFn)); } 68 private: 69 R (*fFn)(Args...); 70 }; 71 72 SkAutoTDelete<Interface> fFunction; 73 }; 74 75 #endif//SkFunction_DEFINED 76