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 20namespace skstd { 21 22// C++17, <variant> 23struct monostate {}; 24 25// C++17, <type_traits> 26template<typename...> struct conjunction : std::true_type { }; 27template<typename T> struct conjunction<T> : T { }; 28template<typename T, typename... Ts> 29struct conjunction<T, Ts...> : std::conditional<bool(T::value), conjunction<Ts...>, T>::type { }; 30 31// C++17, std::data, std::size 32template<typename Container> 33constexpr auto data(Container& c) -> decltype(c.data()) { return c.data(); } 34template<typename Container> 35constexpr auto data(const Container& c) -> decltype(c.data()) { return c.data(); } 36template<typename Array, size_t N> 37constexpr auto data(Array(&a)[N]) -> decltype(a) { return a; } 38template<typename T> 39constexpr const T* data(std::initializer_list<T> i) { return i.begin(); } 40 41template<typename Container> 42constexpr auto size(Container& c) -> decltype(c.size()) { return c.size(); } 43template<typename Array, size_t N> 44constexpr size_t size(Array(&)[N]) { return N; } 45template<typename T> 46constexpr 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. 50namespace 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. 56template <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}; 59template <typename D, typename S> using copy_const_t = typename copy_const<D, S>::type; 60 61template <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}; 64template <typename D, typename S> using copy_volatile_t = typename copy_volatile<D, S>::type; 65 66template <typename D, typename S> struct copy_cv { 67 using type = copy_volatile_t<copy_const_t<D, S>, S>; 68}; 69template <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> 74template <typename D, typename S> using same_const = copy_const<std::remove_const_t<D>, S>; 75template <typename D, typename S> using same_const_t = typename same_const<D, S>::type; 76template <typename D, typename S> using same_volatile =copy_volatile<std::remove_volatile_t<D>,S>; 77template <typename D, typename S> using same_volatile_t = typename same_volatile<D, S>::type; 78template <typename D, typename S> using same_cv = copy_cv<std::remove_cv_t<D>, S>; 79template <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type; 80 81} // namespace sknonstd 82 83template <typename Container> 84constexpr int SkCount(const Container& c) { return SkTo<int>(skstd::size(c)); } 85 86#endif 87