memgraph/include/utils/iterator/combined.hpp
2016-09-08 13:25:52 +01:00

64 lines
1.6 KiB
C++

#pragma once
#include "utils/iterator/composable.hpp"
#include "utils/iterator/iterator_base.hpp"
namespace iter
{
// Class which Combined two iterators IT1 and IT2. Both return values T
// T - type of return value
// IT1 - first iterator type
// IT2 - second iterator type
template <class T, class IT1, class IT2>
class Combined : public IteratorBase<T>,
public Composable<T, Combined<T, IT1, IT2>>
{
public:
Combined() = delete;
// Combined operation is designed to be used in chained calls which operate
// on a iterator. Combined will in that usecase receive other iterator by
// value and std::move is a optimization for it.
Combined(IT1 &&iter1, IT2 &&iter2)
: iter1(Option<IT1>(std::move(iter1))),
iter2(Option<IT2>(std::move(iter2)))
{
}
// Return values first from first iterator then from second.
Option<T> next() final
{
if (iter1.is_present()) {
auto ret = iter1.get().next();
if (ret.is_present()) {
return std::move(ret);
} else {
iter1.take();
}
}
return iter2.next();
}
Count count() final
{
return iter1.map_or([](auto &it) { return it.count(); }, 0) +
iter2.count();
}
private:
Option<IT1> iter1;
IT2 iter2;
};
template <class IT1, class IT2>
auto make_combined(IT1 &&iter1, IT2 &&iter2)
{
// Compiler cant deduce type T. decltype is here to help with it.
return Combined<decltype(iter1.next().take()), IT1, IT2>(std::move(iter1),
std::move(iter2));
}
}