diff options
author | 2015-08-05 12:09:57 -0700 | |
---|---|---|
committer | 2015-08-05 12:09:57 -0700 | |
commit | 2bd028590d9db472e5b9ee44ca8961be5c036432 (patch) | |
tree | 409badcf9b89e54d97ce13ded0fca541abdd2aed /include | |
parent | 2fe7923f7e74f901a17afba7609d71a1220bdc60 (diff) |
Add skstd::move and skstd::forward.
Since we can't use the c++11 standard library, re-implement the bits
we want to use now.
TBR=reed@google.com
The next CL is try to move SkTemplates into private.
Review URL: https://codereview.chromium.org/1273813002
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkTemplates.h | 27 | ||||
-rw-r--r-- | include/private/SkFunction.h | 9 | ||||
-rw-r--r-- | include/private/SkTLogic.h | 27 |
3 files changed, 47 insertions, 16 deletions
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h index 2ddc5be225..ddf6681a11 100644 --- a/include/core/SkTemplates.h +++ b/include/core/SkTemplates.h @@ -10,6 +10,7 @@ #ifndef SkTemplates_DEFINED #define SkTemplates_DEFINED +#include "../private/SkTLogic.h" #include "SkMath.h" #include "SkTypes.h" #include <limits.h> @@ -27,16 +28,22 @@ */ template<typename T> inline void sk_ignore_unused_variable(const T&) { } -/** - * SkTIsConst<T>::value is true if the type T is const. - * The type T is constrained not to be an array or reference type. - */ -template <typename T> struct SkTIsConst { - static T* t; - static uint16_t test(const volatile void*); - static uint32_t test(volatile void *); - static const bool value = (sizeof(uint16_t) == sizeof(test(t))); -}; +namespace skstd { + +template <typename T> inline remove_reference_t<T>&& move(T&& t) { + return static_cast<remove_reference_t<T>&&>(t); +} + +template <typename T> inline T&& forward(remove_reference_t<T>& t) /*noexcept*/ { + return static_cast<T&&>(t); +} +template <typename T> inline T&& forward(remove_reference_t<T>&& t) /*noexcept*/ { + static_assert(!is_lvalue_reference<T>::value, + "Forwarding an rvalue reference as an lvalue reference is not allowed."); + return static_cast<T&&>(t); +} + +} // namespace skstd ///@{ /** SkTConstType<T, CONST>::type will be 'const T' if CONST is true, 'T' otherwise. */ diff --git a/include/private/SkFunction.h b/include/private/SkFunction.h index 8e41cba929..024ba7c9b2 100644 --- a/include/private/SkFunction.h +++ b/include/private/SkFunction.h @@ -35,13 +35,10 @@ public: R operator()(Args... args) const { SkASSERT(fFunction.get()); - return fFunction->call(Forward(args)...); + return fFunction->call(skstd::forward<Args>(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 Interface { virtual ~Interface() {} virtual R call(Args...) const = 0; @@ -53,7 +50,7 @@ private: public: LambdaImpl(const Fn& fn) : fFn(fn) {} - R call(Args... args) const override { return fFn(Forward(args)...); } + R call(Args... args) const override { return fFn(skstd::forward<Args>(args)...); } Interface* clone() const override { return SkNEW_ARGS(LambdaImpl<Fn>, (fFn)); } private: Fn fFn; @@ -63,7 +60,7 @@ private: public: FnPtrImpl(R (*fn)(Args...)) : fFn(fn) {} - R call(Args... args) const override { return fFn(Forward(args)...); } + R call(Args... args) const override { return fFn(skstd::forward<Args>(args)...); } Interface* clone() const override { return SkNEW_ARGS(FnPtrImpl, (fFn)); } private: R (*fFn)(Args...); diff --git a/include/private/SkTLogic.h b/include/private/SkTLogic.h index d188242446..2710d6d1cf 100644 --- a/include/private/SkTLogic.h +++ b/include/private/SkTLogic.h @@ -18,6 +18,8 @@ #ifndef SkTLogic_DEFINED #define SkTLogic_DEFINED +#include <stdint.h> + /** Represents a templated integer constant. * Pre-C++11 version of std::integral_constant. */ @@ -108,4 +110,29 @@ public: \ static const bool value = sizeof(func<T>(NULL)) == sizeof(uint8_t); \ } +namespace skstd { + +/** SkTRemoveReference<T>::type is the type of T with any top-level lvalue or rvalue removed. */ +template <typename T> struct remove_reference { typedef T type; }; +template <typename T> struct remove_reference<T&> { typedef T type; }; +template <typename T> struct remove_reference<T&&> { typedef T type; }; +template <typename T> using remove_reference_t = typename remove_reference<T>::type; + +/** SkTIsLValueReference<T>::value is true if the type T is an lvalue reference. */ +template <typename T> struct is_lvalue_reference : SkFalse {}; +template <typename T> struct is_lvalue_reference<T&> : SkTrue {}; + +} // namespace skstd + +/** + * SkTIsConst<T>::value is true if the type T is const. + * The type T is constrained not to be an array or reference type. + */ +template <typename T> struct SkTIsConst { + static T* t; + static uint16_t test(const volatile void*); + static uint32_t test(volatile void *); + static const bool value = (sizeof(uint16_t) == sizeof(test(t))); +}; + #endif |