1 /* 2 * Copyright 2013 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 * This header provides some std:: features early in the skstd namespace 9 * and several Skia-specific additions in the sknonstd namespace. 10 */ 11 12 #ifndef SkTLogic_DEFINED 13 #define SkTLogic_DEFINED 14 15 #include <cstddef> 16 #include <type_traits> 17 #include <utility> 18 #include "include/private/SkTo.h" 19 20 namespace skstd { 21 22 // C++17, <variant> 23 struct monostate {}; 24 25 // C++17, <type_traits> 26 template<typename...> struct conjunction : std::true_type { }; 27 template<typename T> struct conjunction<T> : T { }; 28 template<typename T, typename... Ts> 29 struct conjunction<T, Ts...> : std::conditional<bool(T::value), conjunction<Ts...>, T>::type { }; 30 31 // C++17, std::data, std::size 32 template<typename Container> 33 constexpr auto data(Container& c) -> decltype(c.data()) { return c.data(); } 34 template<typename Container> 35 constexpr auto data(const Container& c) -> decltype(c.data()) { return c.data(); } 36 template<typename Array, size_t N> 37 constexpr auto data(Array(&a)[N]) -> decltype(a) { return a; } 38 template<typename T> 39 constexpr const T* data(std::initializer_list<T> i) { return i.begin(); } 40 41 template<typename Container> 42 constexpr auto size(Container& c) -> decltype(c.size()) { return c.size(); } 43 template<typename Array, size_t N> 44 constexpr size_t size(Array(&)[N]) { return N; } 45 template<typename T> 46 constexpr const T* size(std::initializer_list<T> i) { return i.end() - i.begin(); } 47 } // namespace skstd 48 49 // The sknonstd namespace contains things we would like to be proposed and feel std-ish. 50 namespace sknonstd { 51 52 // The name 'copy' here is fraught with peril. In this case it means 'append', not 'overwrite'. 53 // Alternate proposed names are 'propagate', 'augment', or 'append' (and 'add', but already taken). 54 // std::experimental::propagate_const already exists for other purposes in TSv2. 55 // These also follow the <dest, source> pattern used by boost. 56 template <typename D, typename S> struct copy_const { 57 using type = std::conditional_t<std::is_const<S>::value, std::add_const_t<D>, D>; 58 }; 59 template <typename D, typename S> using copy_const_t = typename copy_const<D, S>::type; 60 61 template <typename D, typename S> struct copy_volatile { 62 using type = std::conditional_t<std::is_volatile<S>::value, std::add_volatile_t<D>, D>; 63 }; 64 template <typename D, typename S> using copy_volatile_t = typename copy_volatile<D, S>::type; 65 66 template <typename D, typename S> struct copy_cv { 67 using type = copy_volatile_t<copy_const_t<D, S>, S>; 68 }; 69 template <typename D, typename S> using copy_cv_t = typename copy_cv<D, S>::type; 70 71 // The name 'same' here means 'overwrite'. 72 // Alternate proposed names are 'replace', 'transfer', or 'qualify_from'. 73 // same_xxx<D, S> can be written as copy_xxx<remove_xxx_t<D>, S> 74 template <typename D, typename S> using same_const = copy_const<std::remove_const_t<D>, S>; 75 template <typename D, typename S> using same_const_t = typename same_const<D, S>::type; 76 template <typename D, typename S> using same_volatile =copy_volatile<std::remove_volatile_t<D>,S>; 77 template <typename D, typename S> using same_volatile_t = typename same_volatile<D, S>::type; 78 template <typename D, typename S> using same_cv = copy_cv<std::remove_cv_t<D>, S>; 79 template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type; 80 81 } // namespace sknonstd 82 83 template <typename Container> 84 constexpr int SkCount(const Container& c) { return SkTo<int>(skstd::size(c)); } 85 86 #endif 87