hb-meta.hh 12.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright © 2018  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Behdad Esfahbod
 */

#ifndef HB_META_HH
#define HB_META_HH

#include "hb.hh"


B
Behdad Esfahbod 已提交
33
/*
34
 * C++ template meta-programming & fundamentals used with them.
B
Behdad Esfahbod 已提交
35 36
 */

B
Behdad Esfahbod 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49
/* Void!  For when we need a expression-type of void. */
struct hb_void_t { typedef void value; };

/* Void meta-function ala std::void_t
 * https://en.cppreference.com/w/cpp/types/void_t */
template<typename... Ts> struct _hb_void_tt { typedef void type; };
template<typename... Ts> using hb_void_tt = typename _hb_void_tt<Ts...>::type;

template<typename Head, typename... Ts> struct _hb_head_tt { typedef Head type; };
template<typename... Ts> using hb_head_tt = typename _hb_head_tt<Ts...>::type;

/* Bool!  For when we need to evaluate type-dependent expressions
 * in a template argument. */
B
Behdad Esfahbod 已提交
50
template <bool b> struct hb_bool_tt { static constexpr bool value = b; };
B
Behdad Esfahbod 已提交
51 52 53 54
typedef hb_bool_tt<true> hb_true_t;
typedef hb_bool_tt<false> hb_false_t;


55 56 57 58 59 60 61 62 63 64 65 66
/* Basic type SFINAE. */

template <bool B, typename T = void> struct hb_enable_if {};
template <typename T>                struct hb_enable_if<true, T> { typedef T type; };
#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
/* Concepts/Requires alias: */
#define hb_requires(Cond) hb_enable_if((Cond))

template <typename T, typename T2> struct hb_is_same : hb_false_t {};
template <typename T>              struct hb_is_same<T, T> : hb_true_t {};
#define hb_is_same(T, T2) hb_is_same<T, T2>::value

67 68
/* Function overloading SFINAE and priority. */

B
Behdad Esfahbod 已提交
69
#define HB_RETURN(Ret, E) -> hb_head_tt<Ret, decltype ((E))> { return (E); }
70 71
#define HB_AUTO_RETURN(E) -> decltype ((E)) { return (E); }
#define HB_VOID_RETURN(E) -> hb_void_tt<decltype ((E))> { (E); }
72 73 74 75 76

template <unsigned Pri> struct hb_priority : hb_priority<Pri - 1> {};
template <>             struct hb_priority<0> {};
#define hb_prioritize hb_priority<16> ()

B
Behdad Esfahbod 已提交
77
#define HB_FUNCOBJ(x) static_const x HB_UNUSED
B
Behdad Esfahbod 已提交
78

B
Behdad Esfahbod 已提交
79

B
Behdad Esfahbod 已提交
80 81 82
template <typename T> struct hb_match_identity { typedef T type; };
template <typename T> using hb_type_identity = typename hb_match_identity<T>::type;

B
Behdad Esfahbod 已提交
83
struct
84
{
B
Behdad Esfahbod 已提交
85
  template <typename T>
B
Behdad Esfahbod 已提交
86
  T* operator () (T& arg) const
B
Behdad Esfahbod 已提交
87
  {
88 89
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
B
Behdad Esfahbod 已提交
90 91 92 93
    /* https://en.cppreference.com/w/cpp/memory/addressof */
    return reinterpret_cast<T*> (
	     &const_cast<char&> (
		reinterpret_cast<const volatile char&> (arg)));
94
#pragma GCC diagnostic pop
B
Behdad Esfahbod 已提交
95
  }
B
Behdad Esfahbod 已提交
96 97
}
HB_FUNCOBJ (hb_addressof);
98

99
template <typename T> static inline T hb_declval ();
B
Behdad Esfahbod 已提交
100
#define hb_declval(T) (hb_declval<T> ())
B
Behdad Esfahbod 已提交
101

B
Behdad Esfahbod 已提交
102 103
template <typename T> struct hb_match_const		{ typedef T type; static constexpr bool value = false; };
template <typename T> struct hb_match_const<const T>	{ typedef T type; static constexpr bool value = true;  };
104
template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
B
Behdad Esfahbod 已提交
105
#define hb_is_const(T) hb_match_const<T>::value
B
Behdad Esfahbod 已提交
106 107 108
template <typename T> struct hb_match_reference		{ typedef T type; static constexpr bool value = false; };
template <typename T> struct hb_match_reference<T &>	{ typedef T type; static constexpr bool value = true;  };
template <typename T> struct hb_match_reference<T &&>	{ typedef T type; static constexpr bool value = true;  };
109
template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
B
Behdad Esfahbod 已提交
110
#define hb_is_reference(T) hb_match_reference<T>::value
B
Behdad Esfahbod 已提交
111 112
template <typename T> struct hb_match_pointer		{ typedef T type; static constexpr bool value = false; };
template <typename T> struct hb_match_pointer<T *>	{ typedef T type; static constexpr bool value = true;  };
113
template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
B
Behdad Esfahbod 已提交
114
#define hb_is_pointer(T) hb_match_pointer<T>::value
B
Behdad Esfahbod 已提交
115

B
Behdad Esfahbod 已提交
116
/* TODO Add feature-parity to std::decay. */
B
Behdad Esfahbod 已提交
117 118
template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;

B
Behdad Esfahbod 已提交
119 120 121 122 123 124 125 126 127 128
#define hb_is_cr_convertible(From, To) \
	( \
	  hb_is_same (hb_decay<From>, hb_decay<To>) && \
	  ( \
	    hb_is_const (From) <= hb_is_const (To) && \
	    hb_is_reference (From) >= hb_is_reference (To) \
	  ) || ( \
	    hb_is_const (To) && hb_is_reference (To) \
	  ) \
	)
129

130

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

template<bool B, class T, class F>
struct _hb_conditional { typedef T type; };
template<class T, class F>
struct _hb_conditional<false, T, F> { typedef F type; };
template<bool B, class T, class F>
using hb_conditional = typename _hb_conditional<B, T, F>::type;


template <typename From, typename To>
struct hb_is_convertible
{
  private:
  static constexpr bool   from_void = hb_is_same (void, hb_decay<From>);
  static constexpr bool     to_void = hb_is_same (void, hb_decay<To>  );
  static constexpr bool either_void = from_void || to_void;
  static constexpr bool   both_void = from_void && to_void;

  static hb_true_t impl2 (hb_conditional<to_void, int, To>);

  template <typename T>
  static auto impl (hb_priority<1>) HB_AUTO_RETURN ( impl2 (hb_declval (T)) )
  template <typename T>
  static hb_false_t impl (hb_priority<0>);
  public:
  static constexpr bool value = both_void ||
		       (!either_void &&
			decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
};
#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value


163 164 165
/* std::move and std::forward */

template <typename T>
166
static hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
167 168

template <typename T>
169
static T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
170
template <typename T>
171
static T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
172

173 174 175
struct
{
  template <typename T> auto
176
  operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
177 178

  template <typename T> auto
179
  operator () (T *v) const HB_AUTO_RETURN (*v)
B
Behdad Esfahbod 已提交
180 181
}
HB_FUNCOBJ (hb_deref);
182

B
Behdad Esfahbod 已提交
183 184 185 186 187 188 189
struct
{
  template <typename T> auto
  operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))

  template <typename T> auto
  operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
B
Behdad Esfahbod 已提交
190 191
}
HB_FUNCOBJ (hb_ref);
B
Behdad Esfahbod 已提交
192

193 194 195 196 197 198
template <typename T>
struct hb_reference_wrapper
{
  hb_reference_wrapper (T v) : v (v) {}
  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
B
Behdad Esfahbod 已提交
199
  operator T () const { return v; }
200 201 202 203 204 205
  T get () const { return v; }
  T v;
};
template <typename T>
struct hb_reference_wrapper<T&>
{
B
Behdad Esfahbod 已提交
206
  hb_reference_wrapper (T& v) : v (hb_addressof (v)) {}
207 208
  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
B
Behdad Esfahbod 已提交
209 210
  operator T& () const { return *v; }
  T& get () const { return *v; }
211 212 213
  T* v;
};

214

B
Behdad Esfahbod 已提交
215
template <typename T> struct hb_is_signed;
B
Behdad Esfahbod 已提交
216 217 218 219 220 221 222 223 224 225 226
template <> struct hb_is_signed<char>			{ static constexpr bool value = CHAR_MIN < 0;	};
template <> struct hb_is_signed<signed char>		{ static constexpr bool value = true;		};
template <> struct hb_is_signed<unsigned char>		{ static constexpr bool value = false;		};
template <> struct hb_is_signed<signed short>		{ static constexpr bool value = true;		};
template <> struct hb_is_signed<unsigned short>		{ static constexpr bool value = false;		};
template <> struct hb_is_signed<signed int>		{ static constexpr bool value = true;		};
template <> struct hb_is_signed<unsigned int>		{ static constexpr bool value = false;		};
template <> struct hb_is_signed<signed long>		{ static constexpr bool value = true;		};
template <> struct hb_is_signed<unsigned long>		{ static constexpr bool value = false;		};
template <> struct hb_is_signed<signed long long>	{ static constexpr bool value = true;		};
template <> struct hb_is_signed<unsigned long long>	{ static constexpr bool value = false;		};
B
Behdad Esfahbod 已提交
227 228
#define hb_is_signed(T) hb_is_signed<T>::value

B
Behdad Esfahbod 已提交
229 230 231 232 233 234 235 236 237 238 239 240
template <typename T> struct hb_int_min;
template <> struct hb_int_min<char>			{ static constexpr char			value = CHAR_MIN;	};
template <> struct hb_int_min<signed char>		{ static constexpr signed char		value = SCHAR_MIN;	};
template <> struct hb_int_min<unsigned char>		{ static constexpr unsigned char	value = 0;		};
template <> struct hb_int_min<signed short>		{ static constexpr signed short		value = SHRT_MIN;	};
template <> struct hb_int_min<unsigned short>		{ static constexpr unsigned short	value = 0;		};
template <> struct hb_int_min<signed int>		{ static constexpr signed int		value = INT_MIN;	};
template <> struct hb_int_min<unsigned int>		{ static constexpr unsigned int		value = 0;		};
template <> struct hb_int_min<signed long>		{ static constexpr signed long		value = LONG_MIN;	};
template <> struct hb_int_min<unsigned long>		{ static constexpr unsigned long	value = 0;		};
template <> struct hb_int_min<signed long long>		{ static constexpr signed long long	value = LLONG_MIN;	};
template <> struct hb_int_min<unsigned long long>	{ static constexpr unsigned long long	value = 0;		};
B
Behdad Esfahbod 已提交
241
#define hb_int_min(T) hb_int_min<T>::value
B
Behdad Esfahbod 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254
template <typename T> struct hb_int_max;
template <> struct hb_int_max<char>			{ static constexpr char			value = CHAR_MAX;	};
template <> struct hb_int_max<signed char>		{ static constexpr signed char		value = SCHAR_MAX;	};
template <> struct hb_int_max<unsigned char>		{ static constexpr unsigned char	value = UCHAR_MAX;	};
template <> struct hb_int_max<signed short>		{ static constexpr signed short		value = SHRT_MAX;	};
template <> struct hb_int_max<unsigned short>		{ static constexpr unsigned short	value = USHRT_MAX;	};
template <> struct hb_int_max<signed int>		{ static constexpr signed int		value = INT_MAX;	};
template <> struct hb_int_max<unsigned int>		{ static constexpr unsigned int		value = UINT_MAX;	};
template <> struct hb_int_max<signed long>		{ static constexpr signed long		value = LONG_MAX;	};
template <> struct hb_int_max<unsigned long>		{ static constexpr unsigned long	value = ULONG_MAX;	};
template <> struct hb_int_max<signed long long>		{ static constexpr signed long long	value = LLONG_MAX;	};
template <> struct hb_int_max<unsigned long long>	{ static constexpr unsigned long long	value = ULLONG_MAX;	};
#define hb_int_max(T) hb_int_max<T>::value
B
Behdad Esfahbod 已提交
255

B
Behdad Esfahbod 已提交
256 257 258 259 260
template <bool is_signed> struct hb_signedness_int;
template <> struct hb_signedness_int<false> { typedef unsigned int value; };
template <> struct hb_signedness_int<true>  { typedef   signed int value; };
#define hb_signedness_int(T) hb_signedness_int<T>::value

B
Behdad Esfahbod 已提交
261 262 263 264 265 266 267 268 269 270 271 272
template <typename T> struct hb_is_integer		{ static constexpr bool value = false;};
template <> struct hb_is_integer<char> 			{ static constexpr bool value = true; };
template <> struct hb_is_integer<signed char> 		{ static constexpr bool value = true; };
template <> struct hb_is_integer<unsigned char> 	{ static constexpr bool value = true; };
template <> struct hb_is_integer<signed short> 		{ static constexpr bool value = true; };
template <> struct hb_is_integer<unsigned short> 	{ static constexpr bool value = true; };
template <> struct hb_is_integer<signed int> 		{ static constexpr bool value = true; };
template <> struct hb_is_integer<unsigned int> 		{ static constexpr bool value = true; };
template <> struct hb_is_integer<signed long> 		{ static constexpr bool value = true; };
template <> struct hb_is_integer<unsigned long> 	{ static constexpr bool value = true; };
template <> struct hb_is_integer<signed long long> 	{ static constexpr bool value = true; };
template <> struct hb_is_integer<unsigned long long> 	{ static constexpr bool value = true; };
B
Behdad Esfahbod 已提交
273 274
#define hb_is_integer(T) hb_is_integer<T>::value

B
Behdad Esfahbod 已提交
275

276
#endif /* HB_META_HH */