ClickHouse/base/ext/enumerate.h

61 lines
2.1 KiB
C++
Raw Normal View History

2015-11-23 19:03:38 +00:00
#pragma once
2017-06-06 17:18:32 +00:00
#include <ext/size.h>
2015-11-23 19:03:38 +00:00
#include <type_traits>
#include <utility>
#include <iterator>
/** \brief Provides a wrapper view around a container, allowing to iterate over it's elements and indices.
* Allow writing code like shown below:
2015-11-23 19:03:38 +00:00
*
* std::vector<T> v = getVector();
* for (const std::pair<const std::size_t, T &> index_and_value : ext::enumerate(v))
* std::cout << "element " << index_and_value.first << " is " << index_and_value.second << std::endl;
2015-11-23 19:03:38 +00:00
*/
namespace ext
{
template <typename It> struct enumerate_iterator
{
using traits = typename std::iterator_traits<It>;
using iterator_category = typename traits::iterator_category;
using value_type = std::pair<const std::size_t, typename traits::value_type>;
using difference_type = typename traits::difference_type;
using reference = std::pair<const std::size_t, typename traits::reference>;
2015-11-23 19:03:38 +00:00
std::size_t idx;
It it;
2015-11-23 19:03:38 +00:00
2019-08-03 11:02:40 +00:00
enumerate_iterator(const std::size_t idx_, It it_) : idx{idx_}, it{it_} {}
2015-11-23 19:03:38 +00:00
auto operator*() const { return reference(idx, *it); }
2015-11-23 19:03:38 +00:00
bool operator!=(const enumerate_iterator & other) const { return it != other.it; }
2015-11-23 19:03:38 +00:00
enumerate_iterator & operator++() { return ++idx, ++it, *this; }
};
2015-11-23 19:03:38 +00:00
template <typename Collection> struct enumerate_wrapper
{
using underlying_iterator = decltype(std::begin(std::declval<Collection &>()));
using iterator = enumerate_iterator<underlying_iterator>;
2015-11-23 19:03:38 +00:00
Collection & collection;
2015-11-23 19:03:38 +00:00
2019-08-03 11:02:40 +00:00
enumerate_wrapper(Collection & collection_) : collection(collection_) {}
2015-11-23 19:03:38 +00:00
auto begin() { return iterator(0, std::begin(collection)); }
auto end() { return iterator(ext::size(collection), std::end(collection)); }
};
2015-11-23 19:03:38 +00:00
template <typename Collection> auto enumerate(Collection & collection)
{
return enumerate_wrapper<Collection>{collection};
}
2015-11-23 19:03:38 +00:00
template <typename Collection> auto enumerate(const Collection & collection)
{
return enumerate_wrapper<const Collection>{collection};
}
2015-11-23 19:03:38 +00:00
}