• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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