[iter/meta] Add hb_is_iterable

This commit is contained in:
Behdad Esfahbod 2018-12-28 14:29:09 -05:00
parent 576d5e2420
commit 8c6cbbdfa3
5 changed files with 46 additions and 20 deletions

View File

@ -43,6 +43,11 @@
* returns rvalues.
*/
/*
* Base classes for iterators.
*/
/* Base class for all iterators. */
template <typename Iter, typename Item = typename Iter::__item_type__>
struct hb_iter_t
@ -98,8 +103,6 @@ struct hb_iter_t
using Name::is_random_access; \
static_assert (true, "")
/* Base class for sorted iterators. Does not enforce anything.
* Just for class taxonomy and requirements. */
template <typename Iter, typename Item = typename Iter::__item_type__>
@ -147,8 +150,25 @@ struct hb_iter_mixin_t
void operator = (const hb_iter_mixin_t &o HB_UNUSED) {}
};
/*
* Meta-programming predicates.
*/
/* Functions operating on iterators or iteratables. */
template<class T, typename B>
struct _hb_is_iterable
{ enum { value = false }; };
template<class T>
struct _hb_is_iterable<T, hb_bool_tt<(bool) sizeof (hb_declval<T> ().iter ())> >
{ enum { value = true }; };
template<class T>
struct hb_is_iterable { enum { value = _hb_is_iterable<T, hb_true_t>::value }; };
#define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
/*
* Algorithms operating on iterators or iteratables.
*/
template <typename C, typename V> inline void
hb_fill (const C& c, const V &v)

View File

@ -35,12 +35,17 @@
*/
/* Void! For when we need a expression-type of void. */
template <typename T> static T hb_declval ();
/* Void! For when we need a expression-type of void. */
struct hb_void_t { typedef void value; };
struct hb_true_t { enum { value = true }; };
struct hb_false_t { enum { value = false }; };
/* Bool! For when we need to evaluate type-dependent expressions
* in a template argument. */
template <bool b> struct hb_bool_tt { enum { value = b }; };
typedef hb_bool_tt<true> hb_true_t;
typedef hb_bool_tt<false> hb_false_t;
template<bool B, class T = void>
@ -49,7 +54,7 @@ struct hb_enable_if {};
template<class T>
struct hb_enable_if<true, T> { typedef T type; };
#define hb_enable_if(Cond) hb_enable_if<Code>::type* = nullptr
#define hb_enable_if(Cond) typename hb_enable_if<Cond>::type* = nullptr
#define hb_enable_if_t(Type, Cond) hb_enable_if<(Cond), Type>::type

View File

@ -28,6 +28,7 @@
#define HB_NULL_HH
#include "hb.hh"
#include "hb-meta.hh"
/*
@ -45,18 +46,16 @@
* https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
*/
template<bool> struct _hb_bool_type {};
template <typename T, typename B>
struct _hb_null_size
{ enum { value = sizeof (T) }; };
template <typename T>
struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
struct _hb_null_size<T, hb_bool_tt<(bool) (1 + (unsigned int) T::min_size)> >
{ enum { value = T::null_size }; };
template <typename T>
struct hb_null_size
{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
{ enum { value = _hb_null_size<T, hb_true_t>::value }; };
#define hb_null_size(T) hb_null_size<T>::value
/* These doesn't belong here, but since is copy/paste from above, put it here. */
@ -68,12 +67,12 @@ template <typename T, typename B>
struct _hb_static_size
{ enum { value = sizeof (T) }; };
template <typename T>
struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
struct _hb_static_size<T, hb_bool_tt<(bool) (1 + (unsigned int) T::min_size)> >
{ enum { value = T::static_size }; };
template <typename T>
struct hb_static_size
{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
{ enum { value = _hb_static_size<T, hb_true_t>::value }; };
#define hb_static_size(T) hb_static_size<T>::value
@ -85,15 +84,15 @@ template <typename T, typename V, typename B>
struct _hb_assign
{ static inline void value (T &o, const V v) { o = v; } };
template <typename T, typename V>
struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
struct _hb_assign<T, V, hb_bool_tt<(bool) (1 + (unsigned int) T::min_size)> >
{ static inline void value (T &o, const V v) { o.set (v); } };
template <typename T>
struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
struct _hb_assign<T, T, hb_bool_tt<(bool) (1 + (unsigned int) T::min_size)> >
{ static inline void value (T &o, const T v) { o = v; } };
template <typename T, typename V>
static inline void hb_assign (T &o, const V v)
{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); }
{ _hb_assign<T, V, hb_true_t>::value (o, v); }
/*

View File

@ -556,8 +556,10 @@ struct ArrayOf
if (unlikely (!c->extend (*this))) return_trace (false);
return_trace (true);
}
template <typename Iter>
bool serialize (hb_serialize_context_t *c, const hb_iter_t<Iter>& items)
template <typename Iterable,
hb_enable_if (hb_is_iterable (Iterable))>
bool serialize (hb_serialize_context_t *c,
const Iterable& items)
{
TRACE_SERIALIZE (this);
unsigned count = items.len ();

View File

@ -630,7 +630,7 @@ template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
#include "hb-atomic.hh"
#include "hb-meta.hh"
#include "hb-mutex.hh"
#include "hb-null.hh"
#include "hb-null.hh" // Requires: hb-meta
#include "hb-dsalgs.hh" // Requires: hb-null
#include "hb-iter.hh" // Requires: hb-dsalgs hb-meta hb-null
#include "hb-debug.hh" // Requires: hb-atomic hb-dsalgs