diff --git a/src/hb-iter.hh b/src/hb-iter.hh index 8d72cbcd0..6540e0efd 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -55,6 +55,7 @@ struct hb_iter_t typedef Iter iter_t; typedef Item item_t; enum { item_size = hb_static_size (Item) }; + enum { is_iter = true }; private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ @@ -88,6 +89,10 @@ struct hb_iter_t }; #define HB_ITER_USING(Name) \ + using typename Name::iter_t; \ + using typename Name::item_t; \ + using Name::item_size; \ + using Name::is_iter; \ using Name::iter; \ using Name::operator bool; \ using Name::len; \ @@ -154,18 +159,49 @@ struct hb_iter_mixin_t * Meta-programming predicates. */ -template +/* hb_is_iterable() */ + +template struct _hb_is_iterable { enum { value = false }; }; -template +template struct _hb_is_iterable ().iter ())> > { enum { value = true }; }; -template +template struct hb_is_iterable { enum { value = _hb_is_iterable::value }; }; #define hb_is_iterable(Iterable) hb_is_iterable::value +/* hb_is_iterator() */ + +/* The following SFINAE fails to match template parameters to hb_iter_t<>. + * As such, just check for member is_iter being there. */ +# if 0 +template char +_hb_is_iterator (T *) {}; +template int +_hb_is_iterator (hb_iter_t *) {}; +static_assert (sizeof (char) != sizeof (int), ""); + +template +struct hb_is_iterator { enum { + value = sizeof (int) == sizeof (_hb_is_iterator (hb_declval ())) +}; }; +#endif + +template +struct _hb_is_iterator +{ enum { value = false }; }; +template +struct _hb_is_iterator > +{ enum { value = true }; }; + +template +struct hb_is_iterator { enum { value = _hb_is_iterator::value }; }; +#define hb_is_iterator(Iterator) hb_is_iterator::value + + /* * Algorithms operating on iterators or iteratables. */ diff --git a/src/hb-meta.hh b/src/hb-meta.hh index ad12cd277..fd6d60fca 100644 --- a/src/hb-meta.hh +++ b/src/hb-meta.hh @@ -48,10 +48,10 @@ typedef hb_bool_tt hb_true_t; typedef hb_bool_tt hb_false_t; -template +template struct hb_enable_if {}; -template +template struct hb_enable_if { typedef T type; }; #define hb_enable_if(Cond) typename hb_enable_if::type* = nullptr diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index b1e2207a6..41cd0c064 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -552,17 +552,18 @@ struct ArrayOf if (unlikely (!c->extend (*this))) return_trace (false); return_trace (true); } - template + template bool serialize (hb_serialize_context_t *c, - const Iterable& items) + Iterator items) { TRACE_SERIALIZE (this); unsigned count = items.len (); if (unlikely (!serialize (c, count))) return_trace (false); - auto iter = items.iter (); - for (unsigned i = 0; i < count; i++, iter++) - hb_assign (arrayZ[i], *iter); + /* TODO Umm. Just exhaust the iterator instead? Being extra + * cautious right now.. */ + for (unsigned i = 0; i < count; i++, items++) + hb_assign (arrayZ[i], *items); return_trace (true); }