| Index: src/core/SkFunction.h
|
| diff --git a/src/core/SkFunction.h b/src/core/SkFunction.h
|
| index 300959342139646064c533c12ef7d3a9bfab821a..98ae789cae2c70d8f29bd542034e0ecf397af691 100644
|
| --- a/src/core/SkFunction.h
|
| +++ b/src/core/SkFunction.h
|
| @@ -27,21 +27,25 @@ public:
|
| explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) > sizeof(void*)), void*) = nullptr)
|
| : fVTable(GetOutlineVTable<Fn>()) {
|
| // We've got a functor larger than a pointer. We've go to copy it onto the heap.
|
| - fFunction = SkNEW_ARGS(Fn, (fn));
|
| + fFunction = SkNEW_ARGS(Fn, (Forward(fn)));
|
| }
|
|
|
| template <typename Fn>
|
| explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) <= sizeof(void*)), void*) = nullptr)
|
| : fVTable(GetInlineVTable<Fn>()) {
|
| // We've got a functor that fits in a pointer. We copy it right inline.
|
| - SkNEW_PLACEMENT_ARGS(&fFunction, Fn, (fn));
|
| + fFunction = NULL; // Quiets a (spurious) warning that fFunction might be uninitialized.
|
| + SkNEW_PLACEMENT_ARGS(&fFunction, Fn, (Forward(fn)));
|
| }
|
|
|
| ~SkFunction() { fVTable.fCleanUp(fFunction); }
|
|
|
| - R operator()(Args... args) { return fVTable.fCall(fFunction, args...); }
|
| + R operator()(Args... args) { return fVTable.fCall(fFunction, Forward(args)...); }
|
|
|
| private:
|
| + // ~= std::forward. This moves its argument if possible, falling back to a copy if not.
|
| + template <typename T> static T&& Forward(T& v) { return (T&&)v; }
|
| +
|
| struct VTable {
|
| R (*fCall)(void*, Args...);
|
| void (*fCleanUp)(void*);
|
| @@ -50,7 +54,9 @@ private:
|
| // Used when fFunction is a function pointer of type R(*)(Args...).
|
| static const VTable& GetFunctionPointerVTable() {
|
| static const VTable vtable = {
|
| - [](void* fn, Args... args) { return reinterpret_cast<R(*)(Args...)>(fn)(args...); },
|
| + [](void* fn, Args... args) {
|
| + return reinterpret_cast<R(*)(Args...)>(fn)(Forward(args)...);
|
| + },
|
| [](void*) { /* Nothing to clean up for function pointers. */ }
|
| };
|
| return vtable;
|
| @@ -60,7 +66,7 @@ private:
|
| template <typename Fn>
|
| static const VTable& GetOutlineVTable() {
|
| static const VTable vtable = {
|
| - [](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(args...); },
|
| + [](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(Forward(args)...); },
|
| [](void* fn) { SkDELETE(static_cast<Fn*>(fn)); },
|
| };
|
| return vtable;
|
| @@ -71,12 +77,12 @@ private:
|
| static const VTable& GetInlineVTable() {
|
| static const VTable vtable = {
|
| [](void* fn, Args... args) {
|
| - union { void* p; Fn f; } pun = { fn };
|
| - return pun.f(args...);
|
| + union { void** p; Fn* f; } pun = { &fn };
|
| + return (*pun.f)(Forward(args)...);
|
| },
|
| [](void* fn) {
|
| - union { void* p; Fn f; } pun = { fn };
|
| - pun.f.~Fn();
|
| + union { void** p; Fn* f; } pun = { &fn };
|
| + (*pun.f).~Fn();
|
| (void)(pun.f); // Otherwise, when ~Fn() is trivial, MSVC complains pun is unused.
|
| }
|
| };
|
| @@ -92,7 +98,5 @@ private:
|
| // - is it worth moving fCall out of the VTable into SkFunction itself to avoid the indirection?
|
| // - should constructors be implicit?
|
| // - make SkFunction copyable
|
| -// - emulate std::forward for moveable functors (e.g. lambdas)
|
| -// - forward args too?
|
|
|
| #endif//SkFunction_DEFINED
|
|
|