[iter] add hb_concat (a, b).
Iterates over a, and then over b.
This commit is contained in:
parent
95329081c2
commit
ca22741110
|
@ -581,6 +581,79 @@ struct
|
|||
}
|
||||
HB_FUNCOBJ (hb_zip);
|
||||
|
||||
/* hb_concat() */
|
||||
|
||||
template <typename A, typename B>
|
||||
struct hb_concat_iter_t :
|
||||
hb_iter_t<hb_concat_iter_t<A, B>, typename A::item_t>
|
||||
{
|
||||
hb_concat_iter_t () {}
|
||||
hb_concat_iter_t (A& a, B& b) : a (a), b (b) {}
|
||||
hb_concat_iter_t (const A& a, const B& b) : a (a), b (b) {}
|
||||
|
||||
|
||||
typedef typename A::item_t __item_t__;
|
||||
static constexpr bool is_random_access_iterator =
|
||||
A::is_random_access_iterator &&
|
||||
B::is_random_access_iterator;
|
||||
static constexpr bool is_sorted_iterator = false;
|
||||
|
||||
__item_t__ __item__ () const
|
||||
{
|
||||
if (!a)
|
||||
return *b;
|
||||
return *a;
|
||||
}
|
||||
|
||||
__item_t__ __item_at__ (unsigned i) const
|
||||
{
|
||||
if (i < a.len())
|
||||
return a[i];
|
||||
return b[i - a.len()];
|
||||
}
|
||||
|
||||
bool __more__ () const { return bool (a) || bool (b); }
|
||||
|
||||
unsigned __len__ () const { return a.len () + b.len (); }
|
||||
|
||||
void __next__ ()
|
||||
{
|
||||
if (a)
|
||||
++a;
|
||||
else
|
||||
++b;
|
||||
}
|
||||
|
||||
void __forward__ (unsigned n)
|
||||
{
|
||||
if (n > a.len ()) {
|
||||
a.__forward__ (a.len ());
|
||||
n -= a.len ();
|
||||
}
|
||||
b.__forward (n);
|
||||
}
|
||||
|
||||
hb_concat_iter_t __end__ () const { return hb_concat_iter_t (a.end (), b.end ()); }
|
||||
bool operator != (const hb_concat_iter_t& o) const
|
||||
{
|
||||
return a != o.a
|
||||
|| b != o.b;
|
||||
}
|
||||
|
||||
private:
|
||||
A a;
|
||||
B b;
|
||||
};
|
||||
struct
|
||||
{ HB_PARTIALIZE(2);
|
||||
template <typename A, typename B,
|
||||
hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
|
||||
hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>>
|
||||
operator () (A&& a, B&& b) const
|
||||
{ return hb_concat_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
|
||||
}
|
||||
HB_FUNCOBJ (hb_concat);
|
||||
|
||||
/* hb_apply() */
|
||||
|
||||
template <typename Appl>
|
||||
|
|
|
@ -114,6 +114,37 @@ test_iterable (const Iterable &lst = Null (Iterable))
|
|||
test_iterator (lst.iter ());
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
static void check_sequential (It it)
|
||||
{
|
||||
int i = 1;
|
||||
for (int v : +it) {
|
||||
assert (v == i++);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_concat ()
|
||||
{
|
||||
hb_vector_t<int> a = {1, 2, 3};
|
||||
hb_vector_t<int> b = {4, 5};
|
||||
|
||||
hb_vector_t<int> c = {};
|
||||
hb_vector_t<int> d = {1, 2, 3, 4, 5};
|
||||
|
||||
auto it1 = hb_concat (a, b);
|
||||
auto it2 = hb_concat (c, d);
|
||||
auto it3 = hb_concat (d, c);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
assert(it1[i] == i + 1);
|
||||
assert(it2[i] == i + 1);
|
||||
assert(it3[i] == i + 1);
|
||||
}
|
||||
|
||||
check_sequential (it1);
|
||||
check_sequential (it2);
|
||||
check_sequential (it3);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
|
@ -282,5 +313,7 @@ main (int argc, char **argv)
|
|||
assert (hb_range (-2, -8, -3).len () == 2);
|
||||
assert (hb_range (-2, -7, -3).len () == 2);
|
||||
|
||||
test_concat ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue