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 16template <typename> class SkFunction; 17 18template <typename R, typename... Args> 19class SkFunction<R(Args...)> { 20public: 21 SkFunction() {} 22 23 template <typename Fn> 24 SkFunction(const Fn& fn) : fFunction(SkNEW_ARGS(LambdaImpl<Fn>, (fn))) {} 25 26 SkFunction(R (*fn)(Args...)) : fFunction(SkNEW_ARGS(FnPtrImpl, (fn))) {} 27 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 36 R operator()(Args... args) const { 37 SkASSERT(fFunction.get()); 38 return fFunction->call(Forward(args)...); 39 } 40 41private: 42 // ~= std::forward. This moves its argument if possible, falling back to a copy if not. 43 template <typename T> static T&& Forward(T& v) { return (T&&)v; } 44 45 struct Interface { 46 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: 54 LambdaImpl(const Fn& fn) : fFn(fn) {} 55 56 R call(Args... args) const override { return fFn(Forward(args)...); } 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: 64 FnPtrImpl(R (*fn)(Args...)) : fFn(fn) {} 65 66 R call(Args... args) const override { return fFn(Forward(args)...); } 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