Implementing the increment of a skipping iterator - c++

I would like to implement an operator over vector that would skip a certain value. This is what I wrote, with the problem I am facing commented:
template<class MyVector>
struct VectorSkipConstIterator : MyVector::const_iterator {
using Base = typename MyVector::const_iterator;
using ValueType = typename MyVector::value_type;
VectorSkipConstIterator(const ValueType &skip) : Base(), skip_(skip){};
VectorSkipConstIterator(Base it_, const ValueType &skip)
: Base(it_), skip_(skip){};
VectorSkipConstIterator &operator++() {
do {
Base::operator++();
} while (/* have not reached the end */ && this->operator*() == skip_);
return *this;
}
private:
ValueType skip_;
};
So, the problem is that operator++ has to stop somewhere (namely, at the end) even if the last value(s) in the vector need to be skipped. How can this be achieved?

One possible way of achieving this is by simply passing the end iterator as an argument to VectorSkipConstIterator, and keeping it in a field.
template<class MyVector>
struct VectorSkipConstIterator : MyVector::const_iterator {
using Base = typename MyVector::const_iterator;
using ValueType = typename MyVector::value_type;
VectorSkipConstIterator(const ValueType &skip, Base end)
: Base(), skip_(skip){}, end_(end)
{
}
VectorSkipConstIterator(Base it_, const ValueType &skip, Base end)
: Base(it_), skip_(skip), end_(end)
{
}
VectorSkipConstIterator &operator++() {
do {
Base::operator++();
} while (*this != end_ && this->operator*() == skip_);
return *this;
}
private:
ValueType skip_;
Base end_;
};
As TartanLlama said in the comments, inheriting from an iterator is not a good idea. Consider implementing your own iterator class from scratch, satisfying the RandomAccessIterator concept.
Another possible (and in my opinion, better) way of achieving what you desire is using an higher-order function:
template <typename TContainer, typename TSkip, typename TF>
void forEachExcept(TContainer&& c, TSkip&& s, TF&& f)
{
for(auto&& x : c)
{
if(x != s) f(x);
}
}
You can use it as follows:
std::vector<int> v{1,2,5,1,6,2,1};
// skip all occurrences of `1`
forEachExcept(v, 1, [](auto x){ std::cout << x; });
// prints "2562"

Related

C++ iterate over vector of objects and apply STL algorithms to member variables

What again is the quick way to iterate over a vector of custom objects but access only a single member in order to apply general STL-algorithms?
struct Foo
{
std::string a;
double b = 1.0;
};
int main()
{
std::vector<Foo> fooVector(20);
// iterate over all members b -- as if we were iterating over a std::vector<double>
std::discrete_distribution<int> dist(/*??*/, /*??*/);
}
With "quick" I mean
no custom iterator -- or only a very lightweight one (--a few lines of code, no boost iterator_facade, etc.),
no modification of the dereferencing operator (--not that quick).
The constructor of std::discrete_distribution<...> doesn't support any explicit way to project values (like a function object optionally applied to transform the result of *it before being used). As a result I think there are three basic approaches:
Use an intermediate std::vector<double> to obtain a range whose iterators yield doubles:
std::vector<double> tmp; // reserve() as desired
std::transform(fooVector.begin(), fooVector.end(),
std::back_inserter(tmp),
[](Foo const& f){ return f.b; });
std::discrete_distribution<int> d(tmp.begin(), tmp.end());
It may viable to use a conversion operator on Foo to convert into a double:
class Foo {
// ...
operator double() const { return this->b; }
};
// ...
std::discrete_distribution<int> d(fooVector.begin(), fooVector.end());
Create a wrapper for the iterator and use that. It doesn't need anything fancy but putting together a simple input iterators is still comparatively involved:
template <typename InIt>
class project_iterator {
InIt it;
public:
explicit project_iterator(InIt it): it(it) {}
double operator*() const { return *this->it; }
project_iterator& operator++() { ++this->it; return *this; }
project_iterator operator++(int) {
project_iterator rc(*this);
this->operator++();
return *this;
}
bool operator==(project_iterator const& other) const {
return this->it == other.it;
}
bool operator!=(project_iterator const& other) const {
return !(*this == other);
}
};
template <typename It>
project_iterator<It> project(It it) {
return project_iterator<It>(it);
}
namespace std {
template <typename It>
class iterator_traits<project_iterator<It> {
public:
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef double value_type;
typedef double& reference;
typedef double* pointer;
typedef std::input_iterator_tag iterator_category;
}
}
// ...
std::discrete_distribution<int> d(project(fooVector.begin()), project(fooVector.end());
There are, obviously, variation on these approaches but I don't think there is anything else which can be done cleverly. What is missing is essentially a general approach to have projections with sequences (I'm normally referring to them as property maps).
Here is the solution mentioned in my comment:
struct LightIterator : public std::vector<Foo>::iterator
{
LightIterator(std::vector<Foo>::iterator it) : std::vector<Foo>::iterator(it) {}
double& operator*() { return std::vector<Foo>::iterator::operator*().b; }
};
Which you can use like this:
Run It Online
std::accumulate(LightIterator{fooVector.begin()},
LightIterator{fooVector.end()},
0.0);
EDIT: #TartanLlama is right about the issue related to the actual type of std::vector<Foo>::iterator.
As an attempt to have a more generic solution, I suggest that you define a wrapper iterator class for when std::vector<Foo>::iterator is a raw pointer. Something like:
(notice that I'm now allowing arbitrary attributes to be selected. More on that later)
template <
typename PointerType,
typename ItemType,
typename AttributeType
>
struct LightIterator_FromPointer : public std::iterator<std::input_iterator_tag,
std::remove_pointer_t<PointerType>>
{
PointerType it;
AttributeType ItemType::* pointerToAttribute;
LightIterator_FromPointer(PointerType it_, AttributeType ItemType::* pointerToAttribute_)
: it(it_)
, pointerToAttribute(pointerToAttribute_)
{}
AttributeType& operator*() { return it->*pointerToAttribute; }
AttributeType* operator->() { return it; }
// input iterator boilerplate: http://en.cppreference.com/w/cpp/concept/InputIterator
using this_t = LightIterator_FromPointer<PointerType, ItemType, AttributeType>; // less typing...
LightIterator_FromPointer(const this_t& other) : it(other.it) {}
bool operator!=(const this_t& other) const { return it != other.it; }
this_t& operator++() { ++it; return *this; }
this_t operator++(const int) { return {it++}; }
};
While still keeping the original "minimal" light iterator for when std::vector<Foo>::iterator is actually a class:
template <
typename IteratorType,
typename ItemType,
typename AttributeType
>
struct LightIterator_FromClass : public IteratorType
{
AttributeType ItemType::* pointerToAttribute;
LightIterator_FromClass(IteratorType it_, AttributeType ItemType::* pointerToAttribute_)
: IteratorType(it_)
, pointerToAttribute(pointerToAttribute_)
{}
AttributeType& operator*() { return IteratorType::operator*().*pointerToAttribute; }
};
Finally, in order to abstract the details of the light iterator type that should be used on the call site, you can define a make_iterator() function that takes care of everything:
template <
typename IteratorType,
typename ItemType,
typename AttributeType
>
typename std::conditional<std::is_pointer<IteratorType>::value,
LightIterator_FromPointer<IteratorType, ItemType, AttributeType>,
LightIterator_FromClass<IteratorType, ItemType, AttributeType>
>::type
make_iterator(IteratorType it, AttributeType ItemType::* pointerToAttribute)
{
return typename std::conditional<std::is_pointer<IteratorType>::value,
LightIterator_FromPointer<IteratorType, ItemType, AttributeType>,
LightIterator_FromClass<IteratorType, ItemType, AttributeType>
>::type(it, pointerToAttribute);
}
The result is a simple calling syntax which (bonus) allows for selecting any attribute, not only Foo::b.
Run It Online
// light iterator from an actual iterator "class"
{
std::vector<Foo> fooVector(20);
double acc = std::accumulate(make_iterator(fooVector.begin(), &Foo::b),
make_iterator(fooVector.end(), &Foo::b),
0.0);
cout << acc << endl;
}
// light iterator from a "pointer" iterator
{
std::array<Foo, 20> fooVector;
double acc = std::accumulate(make_iterator(fooVector.begin(), &Foo::b),
make_iterator(fooVector.end(), &Foo::b),
0.0);
cout << acc << endl;
}

std::transform to arbitrary container

I want to write universal function that receives container1 with values [a1, .. , an] and returns another container2 with values [convert(a1), .. , convert(an)].
If container2 is std::vector, the problem is trivial, std::transform does exactly what I want. The following function can deal with arbitrary container2 and container1
template<class ToType, class FromType>
ToType convert(const FromType& from)
{
std::vector<typename ToType::value_type> tmp;
std::transform(from.begin(), from.end(),
std::back_inserter(tmp),
[](const typename FromType::value_type& f) {
return convert<typename ToType::value_type>(f);
});
return ToType(tmp.begin(), tmp.end());
}
But it does addition copy. Does anyone know how to do better?
Check out this answer to Is it possible to write a C++ template to check for a function's existence?. You can use SFINAE to detect if a function of your destination container exists (such as push_back or insert) or if an inserter for your container exists (such as inserter or back_inserter), and behave accordingly.
Another way is to create a fake iterator:
template <class T, class U>
struct ConvertIterator {
typedef T dest_type;
typedef U it_type;
ConvertIterator(U&& val) : iterator(std::forward<U>(val)) {
}
bool operator == (const ConvertIterator &other) const {
return iterator == other.iterator;
}
bool operator != (const ConvertIterator &other) const {
return iterator != other.iterator;
}
dest_type operator * () const {
return convert<dest_type>(*iterator);
}
ConvertIterator<T, U> & operator ++() {
++iterator;
return *this;
}
it_type iterator;
};
and then:
template<class ToType, class FromType>
ToType convert(const FromType& from)
{
typedef ConvertIterator<typename ToType::value_type, decltype(from.begin()) > convert_it;
return ToType(convert_it(from.begin()), convert_it(from.end()));
}
Here is a function-based converting iterator. It has all the proper typedefs for a forward iterator. We could upgrade it to support all of the tag properties of the incoming Base iterator type if we chose:
template<
class Base,
class F,
class R=typename std::result_of<F(decltype(*std::declval<Base const&>()))>::type
>
struct convert_iterator:
std::iterator<std::forward_iterator_tag,typename std::decay<R>::type>
{
Base it;
F f;
template<class It, class Func>
convert_iterator(It&&base, Func&&func):it(std::forward<It>(base)),
// defaulted stuff:
convert_iterator()=default;
convert_iterator(convert_iterator const&)=default;
convert_iterator(convert_iterator &&)=default;
convert_iterator& operator=(convert_iterator const&)=default;
convert_iterator& operator=(convert_iterator &&)=default;
bool operator==(convert_iterator const&other) const {
return it == other.it;
}
bool operator!=(convert_iterator const&other) const { return !(*this==other); }
// a bit overkill, but rvalue and lvalue overrides for these:
R operator*() const& {
return f(*it);
}
R operator*() & {
return f(*it);
}
R operator*() const&& {
return std::move(f)(*std::move(it));
}
R operator*() && {
return std::move(f)(*std::move(it));
}
// normal pre-increment:
convert_iterator& operator++()& {
++it;
return *this;
}
// pre-increment when we are guaranteed not to be used again can be done differently:
convert_iterator operator++()&& {
return {std::next(std::move(it)), std::forward<F>(f)};
}
// block rvalue post-increment like a boss:
convert_iterator operator++(int)& {
return {it++, f};
}
};
a helper function to create them:
template< class Base, class F >
convert_iterator<typename std::decay<Base>::type,typename std::decay<F>::type>
make_convert_iterator(Base&& b, F&& f) { return {std::forward<Base>(b), std::forward<F>(f)}; }
Next I create a class that handles conversion. Specialization lets us dispatch differently for containers and scalars:
// for scalars:
template<class ToType,class=void>
struct converter {
template<class FromType>
ToType operator()(FromType&& from)const{ return std::forward<FromType>(from); }
};
// attempt at SFINAE test for container:
template<class ToContainer>
struct converter<ToContainer, (void)(
typename std::iterator_traits<
typename std::decay<decltype(std::begin(std::declval<ToContainer&>())>::type
>::value_type
)>
{
using std::begin; using std::end;
using R=std::iterator_traits<typename std::decay<decltype(begin(std::declval<ToContainer&>()))>::type>::value_type;
template<class FromType, class T=decltype(*begin(std::declval<FromType>())>
ToContainer operator()(FromType&& from) const {
auto sub_convert = [](T&& t)->R{
return converter<R>{}(std::forward<T>(t));
};
return {
make_convert_iterator(begin(std::forward<From>(from)), sub_convert),
make_convert_iterator(end(std::forward<From>(from)), sub_convert)
};
};
};
The action convert function is now a one-liner:
template<class ToType>
ToType convert(FromType&& from)
{
return converter<ToType>{}(std::forward<FromType>(from));
}

Common code to iterate through different types of collections

Is there an elegant solution to use common code to iterate through hash_map/unordered_map and list/vector collections?
An example:
template<typename collection>
class multicast
{
public:
typedef collection collection_type;
private:
collection_type& m_channels;
public:
multicast(collection_type& channels) : m_channels(channels) { }
void operator ()(const buffer::ptr& head, const buffer::ptr& cnt)
{
for each(collection_type::value_type& ch in m_channels)
ch->send(head, cnt); /* this is where the magic should happen? */
}
}
This code obviously fails to compile when collection_type is unordered_map since collection_type::value_type is a pair so the code that access the actual value should be different: ch.second->send(head, cnt) instead of ch->send(head, cnt). So what would be the most elegant way to get rid of key part when it is not needed?
Yes:
for (auto & x : collection) { do_stuff_with(x); }
Alternatively:
for (auto it = std::begin(collection), end = std::end(collection); it != end; ++it)
{
do_stuff_with(*it);
}
If neither range-based for nor auto are available, you could write a template which takes a container C and use C::value_type and C::iterator; or you could make a template which accepts a pair of iterators of type Iter and uses std::iterator_traits<Iter>::value_type for the element value type.
Thirdly, you can use for_each and a lambda:
std::for_each(colllection.begin(), collection.end(),
[](collection::value_type & x) { do_stuff_with(x); });
To accommodate for both single-element and pair-element containers, you can build a little wrapper:
template <typename T> struct get_value_impl
{
typedef T value_type;
static value_type & get(T & t) { return t; }
};
template <typename K, typename V> struct get_value_impl<std::pair<K, V>>
{
typedef V value_type;
static value_type & get(std::pair<K,V> & p) { return p.second; }
};
template <typename T>
typename get_value_impl<T>::value_type & get_value(T & t)
{
return get_value_impl<T>::get(t);
}
Now you can use get_value(x) or get_value(*it) to get the value only.
The problem is that list/vector contains just a value, while map-s contains a pair of key-value. They are not the same thing, and to iterate the same way you shold at least define what part of the pair you are interested in.
Once defined, you essentially need a "derefence" operation that accepts an iterator, and -in case it has as a value_type a pair, return the second element, oterwise just dereference it.
// default case, returning itself
template<class T>
T& get_val(T& t) { return t; }
// case for pair (derefence for a map iterator)
template<class K, class V>
V& get_val(std::pair<const K, V>& s) { return s.second; }
// iterator dereference
template<class Iter>
decltype(get_val(*Iter()) deref_iter(const Iter& i)
{ return get_val(*i); }
Of course, const_iter version are also required, if needed.
Now:
for(auto i=container.begin(); i!=container-end(); ++i)
do_something_with(deref_iter(i));
will be the same whatever the container.

How to get the index of a value in a vector using for_each?

I have the following code (compiler: MSVC++ 10):
std::vector<float> data;
data.push_back(1.0f);
data.push_back(1.0f);
data.push_back(2.0f);
// lambda expression
std::for_each(data.begin(), data.end(), [](int value) {
// Can I get here index of the value too?
});
What I want in the above code snippet is to get the index of the value in the data vector inside the lambda expression. It seems for_each only accepts a single parameter function. Is there any alternative to this using for_each and lambda?
In C++14 thanks to generalized lambda captures you can do something like so:
std::vector<int> v(10);
std::for_each(v.begin(), v.end(), [idx = 0] (int i) mutable {
// your code...
++idx; // 0, 1, 2... 9
});
Alternatively, you can use &value - &data[0], although it might be a bit more expensive.
std::for_each(data.begin(), data.end(), [&data](float const& value) {
int idx = &value - &data[0];
});
I don't think you can capture the index, but you can use an outer variable to do the indexing, capturing it into the lambda:
int j = 0;
std::for_each(data.begin(), data.end(), [&j](float const& value) {
j++;
});
std::cout << j << std::endl;
This prints 3, as expected, and j holds the value of the index.
If you want the actual iterator, you maybe can do it similarly:
std::vector<float>::const_iterator it = data.begin();
std::for_each(data.begin(), data.end(), [&it](float const& value) {
// here "it" has the iterator
++it;
});
Something like this:
template <typename IteratorT, typename FunctionT>
FunctionT enumerate(IteratorT first,
IteratorT last,
typename std::iterator_traits<IteratorT>::difference_type initial,
FunctionT func)
{
for (;first != last; ++first, ++initial)
func(initial, *first);
return func;
}
Used as:
enumerate(data.begin(), data.end(), 0, [](unsigned index, float val)
{
std::cout << index << " " << val << std::endl;
});
I think that the simplest way is to use std::accumulate:
std::accumulate(data.begin(), data.end(), 0, [](int index, float const& value)->int{
...
return index + 1;
});
This solution works with any container and it don't require a variable or custom classes.
Another way to wrap iterators for enumerate:
Required headers:
#include <algorithm>
#include <iterator>
#include <utility>
Wrapping iterator:
template<class Iter, class Offset=int>
struct EnumerateIterator : std::iterator<std::input_iterator_tag, void, void, void, void> {
Iter base;
Offset n;
EnumerateIterator(Iter base, Offset n = Offset()) : base (base), n (n) {}
EnumerateIterator& operator++() { ++base; ++n; return *this; }
EnumerateIterator operator++(int) { auto copy = *this; ++*this; return copy; }
friend bool operator==(EnumerateIterator const& a, EnumerateIterator const& b) {
return a.base == b.base;
}
friend bool operator!=(EnumerateIterator const& a, EnumerateIterator const& b) {
return !(a == b);
}
struct Pair {
Offset first;
typename std::iterator_traits<Iter>::reference second;
Pair(Offset n, Iter iter) : first (n), second(*iter) {}
Pair* operator->() { return this; }
};
Pair operator*() { return Pair(n, base); }
Pair operator->() { return Pair(n, base); }
};
Enumerate overloads:
template<class Iter, class Func>
Func enumerate(Iter begin, Iter end, Func func) {
typedef EnumerateIterator<Iter> EI;
return std::for_each(EI(begin), EI(end), func);
}
template<class T, int N, class Func>
Func enumerate(T (&a)[N], Func func) {
return enumerate(a, a + N, func);
}
template<class C, class Func>
Func enumerate(C& c, Func func) {
using std::begin;
using std::end;
return enumerate(begin(c), end(c), func);
}
Copied test from James:
#include <array>
#include <iostream>
struct print_pair {
template<class Pair>
void operator()(Pair const& p) {
std::cout << p.first << ": " << p.second << "\n";
}
};
int main() {
std::array<float, 5> data = {1, 3, 5, 7, 9};
enumerate(data, print_pair());
return 0;
}
I don't include providing an offset here; though it's fully ready in EnumerateIterator to start at otherwise than 0. The choice left is what type to make the offset and whether to add overloads for the extra parameter or use a default value. (No reason the offset has to be the iterator's difference type, e.g. what if you made it some date related type, with each iteration corresponding to the next day?)
Roger Pate suggested in a comment to my other answer creating an iterator wrapper that performs the enumeration. Implementing it was a bit of a beating.
This iterator wrapper takes a forward iterator whose value type is T (called the "inner iterator") and transforms it into a forward iterator whose value type is a pair<int, T&>, where int is the distance type of the inner iterator.
This would be quite simple, except for two things:
The std::pair constructor takes its arguments by const reference so we can't initialize a data member of type T&; we'll have to create our own pair type for the iterator.
In order to support the correct semantics for the iterator, we need an lvalue (operator* needs to return a reference and operator-> needs to return a pointer), so the pair needs to be a data member of the iterator. Since it contains a reference, we'll need a way to "reset" it and we'll need it to be lazily initialized so that we can correctly handle end iterators. boost::optional<T> seems not to like it if T is not assignable, so we'll write our own simple lazy<T>.
The lazy<T> wrapper:
#include <new>
#include <type_traits>
// A trivial lazily-initialized object wrapper; does not support references
template<typename T>
class lazy
{
public:
lazy() : initialized_(false) { }
lazy(const T& x) : initialized_(false) { construct(x); }
lazy(const lazy& other)
: initialized_(false)
{
if (other.initialized_)
construct(other.get());
}
lazy& operator=(const lazy& other)
{
// To the best of my knowledge, there is no clean way around the self
// assignment check here since T may not be assignable
if (this != &other)
construct(other.get());
return *this;
}
~lazy() { destroy(); }
void reset() { destroy(); }
void reset(const T& x) { construct(x); }
T& get() { return reinterpret_cast< T&>(object_); }
const T& get() const { return reinterpret_cast<const T&>(object_); }
private:
// Ensure lazy<T> is not instantiated with T as a reference type
typedef typename std::enable_if<
!std::is_reference<T>::value
>::type ensure_t_is_not_a_reference;
void construct(const T& x)
{
destroy();
new (&object_) T(x);
initialized_ = true;
}
void destroy()
{
if (initialized_)
reinterpret_cast<T&>(object_).~T();
initialized_ = false;
}
typedef typename std::aligned_storage<
sizeof T,
std::alignment_of<T>::value
>::type storage_type;
storage_type object_;
bool initialized_;
};
The enumerating_iterator:
#include <iterator>
#include <type_traits>
// An enumerating iterator that transforms an iterator with a value type of T
// into an iterator with a value type of pair<index, T&>.
template <typename IteratorT>
class enumerating_iterator
{
public:
typedef IteratorT inner_iterator;
typedef std::iterator_traits<IteratorT> inner_traits;
typedef typename inner_traits::difference_type inner_difference_type;
typedef typename inner_traits::reference inner_reference;
// A stripped-down version of std::pair to serve as a value type since
// std::pair does not like having a reference type as a member.
struct value_type
{
value_type(inner_difference_type f, inner_reference s)
: first(f), second(s) { }
inner_difference_type first;
inner_reference second;
};
typedef std::forward_iterator_tag iterator_category;
typedef inner_difference_type difference_type;
typedef value_type& reference;
typedef value_type* pointer;
explicit enumerating_iterator(inner_iterator it = inner_iterator(),
difference_type index = 0)
: it_(it), index_(index) { }
enumerating_iterator& operator++()
{
++index_;
++it_;
return *this;
}
enumerating_iterator operator++(int)
{
enumerating_iterator old_this(*this);
++*this;
return old_this;
}
const value_type& operator*() const
{
value_.reset(value_type(index_, *it_));
return value_.get();
}
const value_type* operator->() const { return &**this; }
friend bool operator==(const enumerating_iterator& lhs,
const enumerating_iterator& rhs)
{
return lhs.it_ == rhs.it_;
}
friend bool operator!=(const enumerating_iterator& lhs,
const enumerating_iterator& rhs)
{
return !(lhs == rhs);
}
private:
// Ensure that the template argument passed to IteratorT is a forward
// iterator; if template instantiation fails on this line, IteratorT is
// not a valid forward iterator:
typedef typename std::enable_if<
std::is_base_of<
std::forward_iterator_tag,
typename std::iterator_traits<IteratorT>::iterator_category
>::value
>::type ensure_iterator_t_is_a_forward_iterator;
inner_iterator it_; //< The current iterator
difference_type index_; //< The index at the current iterator
mutable lazy<value_type> value_; //< Pair to return from op* and op->
};
// enumerating_iterator<T> construction type deduction helpers
template <typename IteratorT>
enumerating_iterator<IteratorT> make_enumerator(IteratorT it)
{
return enumerating_iterator<IteratorT>(it);
}
template <typename IteratorT, typename DifferenceT>
enumerating_iterator<IteratorT> make_enumerator(IteratorT it, DifferenceT idx)
{
return enumerating_iterator<IteratorT>(it, idx);
}
A test stub:
#include <algorithm>
#include <array>
#include <iostream>
struct print_pair
{
template <typename PairT>
void operator()(const PairT& p)
{
std::cout << p.first << ": " << p.second << std::endl;
}
};
int main()
{
std::array<float, 5> data = { 1, 3, 5, 7, 9 };
std::for_each(make_enumerator(data.begin()),
make_enumerator(data.end()),
print_pair());
}
This has been minimally tested; Comeau and g++ 4.1 both accept it if I remove the C++0x type traits and aligned_storage (I don't have a newer version of g++ on this laptop to test with). Please let me know if you find any bugs.
I'm very interested in suggestions about how to improve this. Specifically, I'd love to know if there is a way around having to use lazy<T>, either by using something from Boost or by modifying the iterator itself. I hope I'm just being dumb and that there's actually a really easy way to implement this more cleanly.
Following the standard convention for C and C++, the first element has index 0, and the last element has index size() - 1.
So you have to do the following;-
std::vector<float> data;
int index = 0;
data.push_back(1.0f);
data.push_back(1.0f);
data.push_back(2.0f);
// lambda expression
std::for_each(data.begin(), data.end(), [&index](float value) {
// Can I get here index of the value too?
cout<<"Current Index :"<<index++; // gets the current index before increment
});
You could also pass a struct as third argument to std::for_each and count the index in it like so:
struct myStruct {
myStruct(void) : index(0) {};
void operator() (float i) { cout << index << ": " << i << endl; index++; }
int index;
};
int main()
{
std::vector data;
data.push_back(1.0f);
data.push_back(4.0f);
data.push_back(8.0f);
// lambda expression
std::for_each(data.begin(), data.end(), myStruct());
return 0;
}
Maybe in the lambda function, pass it a int& instead of value int, so you'd have the address. & then you could use that to deduce your position from the first item
Would that work? I don't know if for_each supports references

Flattening iterator

Is there any existing iterator implementation (perhaps in boost) which implement some sort of flattening iterator?
For example:
unordered_set<vector<int> > s;
s.insert(vector<int>());
s.insert({1,2,3,4,5});
s.insert({6,7,8});
s.insert({9,10,11,12});
flattening_iterator<unordered_set<vector<int> >::iterator> it( ... ), end( ... );
for(; it != end; ++it)
{
cout << *it << endl;
}
//would print the numbers 1 through 12
I don't know of any implementation in a major library, but it looked like an interesting problem so I wrote a basic implementation. I've only tested it with the test case I present here, so I don't recommend using it without further testing.
The problem is a bit trickier than it looks because some of the "inner" containers may be empty and you have to skip over them. This means that advancing the flattening_iterator by one position may actually advance the iterator into the "outer" container by more than one position. Because of this, the flattening_iterator needs to know where the end of the outer range is so that it knows when it needs to stop.
This implementation is a forward iterator. A bidirectional iterator would also need to keep track of the beginning of the outer range. The flatten function templates are used to make constructing flattening_iterators a bit easier.
#include <iterator>
// A forward iterator that "flattens" a container of containers. For example,
// a vector<vector<int>> containing { { 1, 2, 3 }, { 4, 5, 6 } } is iterated as
// a single range, { 1, 2, 3, 4, 5, 6 }.
template <typename OuterIterator>
class flattening_iterator
{
public:
typedef OuterIterator outer_iterator;
typedef typename OuterIterator::value_type::iterator inner_iterator;
typedef std::forward_iterator_tag iterator_category;
typedef typename inner_iterator::value_type value_type;
typedef typename inner_iterator::difference_type difference_type;
typedef typename inner_iterator::pointer pointer;
typedef typename inner_iterator::reference reference;
flattening_iterator() { }
flattening_iterator(outer_iterator it) : outer_it_(it), outer_end_(it) { }
flattening_iterator(outer_iterator it, outer_iterator end)
: outer_it_(it),
outer_end_(end)
{
if (outer_it_ == outer_end_) { return; }
inner_it_ = outer_it_->begin();
advance_past_empty_inner_containers();
}
reference operator*() const { return *inner_it_; }
pointer operator->() const { return &*inner_it_; }
flattening_iterator& operator++()
{
++inner_it_;
if (inner_it_ == outer_it_->end())
advance_past_empty_inner_containers();
return *this;
}
flattening_iterator operator++(int)
{
flattening_iterator it(*this);
++*this;
return it;
}
friend bool operator==(const flattening_iterator& a,
const flattening_iterator& b)
{
if (a.outer_it_ != b.outer_it_)
return false;
if (a.outer_it_ != a.outer_end_ &&
b.outer_it_ != b.outer_end_ &&
a.inner_it_ != b.inner_it_)
return false;
return true;
}
friend bool operator!=(const flattening_iterator& a,
const flattening_iterator& b)
{
return !(a == b);
}
private:
void advance_past_empty_inner_containers()
{
while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end())
{
++outer_it_;
if (outer_it_ != outer_end_)
inner_it_ = outer_it_->begin();
}
}
outer_iterator outer_it_;
outer_iterator outer_end_;
inner_iterator inner_it_;
};
template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator it)
{
return flattening_iterator<Iterator>(it, it);
}
template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator first, Iterator last)
{
return flattening_iterator<Iterator>(first, last);
}
The following is a minimal test stub:
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
int main()
{
// Generate some test data: it looks like this:
// { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } }
std::vector<std::vector<int>> v(3);
int i(0);
for (auto it(v.begin()); it != v.end(); ++it)
{
it->push_back(i++); it->push_back(i++);
it->push_back(i++); it->push_back(i++);
}
// Flatten the data and print all the elements:
for (auto it(flatten(v.begin(), v.end())); it != v.end(); ++it)
{
std::cout << *it << ", ";
}
std::cout << "\n";
// Or, since the standard library algorithms are awesome:
std::copy(flatten(v.begin(), v.end()), flatten(v.end()),
std::ostream_iterator<int>(std::cout, ", "));
}
Like I said at the beginning, I haven't tested this thoroughly. Let me know if you find any bugs and I'll be happy to correct them.
I decided to "improve" a bit on the flattening iterator concept, though as noted by James you are stuck using Ranges (except for the inner most container), so I just used ranges through and through and thus obtained a flattened range, with an arbitrary depth.
First I used a building brick:
template <typename C>
struct iterator { using type = typename C::iterator; };
template <typename C>
struct iterator<C const> { using type = typename C::const_iterator; };
And then defined a (very minimal) ForwardRange concept:
template <typename C>
class ForwardRange {
using Iter = typename iterator<C>::type;
public:
using pointer = typename std::iterator_traits<Iter>::pointer;
using reference = typename std::iterator_traits<Iter>::reference;
using value_type = typename std::iterator_traits<Iter>::value_type;
ForwardRange(): _begin(), _end() {}
explicit ForwardRange(C& c): _begin(begin(c)), _end(end(c)) {}
// Observers
explicit operator bool() const { return _begin != _end; }
reference operator*() const { assert(*this); return *_begin; }
pointer operator->() const { assert(*this); return &*_begin; }
// Modifiers
ForwardRange& operator++() { assert(*this); ++_begin; return *this; }
ForwardRange operator++(int) { ForwardRange tmp(*this); ++*this; return tmp; }
private:
Iter _begin;
Iter _end;
}; // class ForwardRange
This is our building brick here, though in fact we could make do with just the rest:
template <typename C, size_t N>
class FlattenedForwardRange {
using Iter = typename iterator<C>::type;
using Inner = FlattenedForwardRange<typename std::iterator_traits<Iter>::value_type, N-1>;
public:
using pointer = typename Inner::pointer;
using reference = typename Inner::reference;
using value_type = typename Inner::value_type;
FlattenedForwardRange(): _outer(), _inner() {}
explicit FlattenedForwardRange(C& outer): _outer(outer), _inner() {
if (not _outer) { return; }
_inner = Inner{*_outer};
this->advance();
}
// Observers
explicit operator bool() const { return static_cast<bool>(_outer); }
reference operator*() const { assert(*this); return *_inner; }
pointer operator->() const { assert(*this); return _inner.operator->(); }
// Modifiers
FlattenedForwardRange& operator++() { ++_inner; this->advance(); return *this; }
FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
private:
void advance() {
if (_inner) { return; }
for (++_outer; _outer; ++_outer) {
_inner = Inner{*_outer};
if (_inner) { return; }
}
_inner = Inner{};
}
ForwardRange<C> _outer;
Inner _inner;
}; // class FlattenedForwardRange
template <typename C>
class FlattenedForwardRange<C, 0> {
using Iter = typename iterator<C>::type;
public:
using pointer = typename std::iterator_traits<Iter>::pointer;
using reference = typename std::iterator_traits<Iter>::reference;
using value_type = typename std::iterator_traits<Iter>::value_type;
FlattenedForwardRange(): _range() {}
explicit FlattenedForwardRange(C& c): _range(c) {}
// Observers
explicit operator bool() const { return static_cast<bool>(_range); }
reference operator*() const { return *_range; }
pointer operator->() const { return _range.operator->(); }
// Modifiers
FlattenedForwardRange& operator++() { ++_range; return *this; }
FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
private:
ForwardRange<C> _range;
}; // class FlattenedForwardRange
And apparently, it works
I arrive a little late here, but I have just published a library (multidim) to deal with such problem. The usage is quite simple: to use your example,
#include "multidim.hpp"
// ... create "s" as in your example ...
auto view = multidim::makeFlatView(s);
// view offers now a flattened view on s
// You can now use iterators...
for (auto it = begin(view); it != end(view); ++it) cout << *it << endl;
// or a simple range-for loop
for (auto value : view) cout << value;
The library is header-only and has no dependencies. Requires C++11 though.
you can make one using iterator facade in boost.
I wrote iterator product which you can use as a template perhaps:
http://code.google.com/p/asadchev/source/browse/trunk/work/cxx/iterator/product.hpp
In addition to the answer of Matthieu, you can automatically count the amount of dimensions of the iterable/container. But first we must set up a rule when something is an iterable/container:
template<class T, class R = void>
struct AliasWrapper {
using Type = R;
};
template<class T, class Enable = void>
struct HasValueType : std::false_type {};
template<class T>
struct HasValueType<T, typename AliasWrapper<typename T::value_type>::Type> : std::true_type {};
template<class T, class Enable = void>
struct HasConstIterator : std::false_type {};
template<class T>
struct HasConstIterator<T, typename AliasWrapper<typename T::const_iterator>::Type> : std::true_type {};
template<class T, class Enable = void>
struct HasIterator : std::false_type {};
template<class T>
struct HasIterator<T, typename AliasWrapper<typename T::iterator>::Type> : std::true_type {};
template<class T>
struct IsIterable {
static constexpr bool value = HasValueType<T>::value && HasConstIterator<T>::value && HasIterator<T>::value;
};
We can count the dimensions as follows:
template<class T, bool IsCont>
struct CountDimsHelper;
template<class T>
struct CountDimsHelper<T, true> {
using Inner = typename std::decay_t<T>::value_type;
static constexpr int value = 1 + CountDimsHelper<Inner, IsIterable<Inner>::value>::value;
};
template<class T>
struct CountDimsHelper<T, false> {
static constexpr int value = 0;
};
template<class T>
struct CountDims {
using Decayed = std::decay_t<T>;
static constexpr int value = CountDimsHelper<Decayed, IsIterable<Decayed>::value>::value;
};
We then can create a view wrapper, that contains a begin() and end() function.
template<class Iterable, int Dims>
class Flatten {
public:
using iterator = FlattenIterator<Iterable, Dims>;
private:
iterator _begin{};
iterator _end{};
public:
Flatten() = default;
template<class I>
explicit Flatten(I&& iterable) :
_begin(iterable),
_end(iterable)
{}
iterator begin() const {
return _begin;
}
iterator end() const {
return _end;
}
};
To make the creation of the object Flatten a bit easier, we define a helper function:
template<class Iterable>
Flatten<std::decay_t<Iterable>, CountDims<Iterable>::value - 1> flatten(Iterable&& iterable) {
return Flatten<std::decay_t<Iterable>, CountDims<Iterable>::value - 1>(iterable);
}
Usage:
std::vector<std::vector<int>> vecs = {{1,2,3}, {}, {4,5,6}};
for (int i : flatten(vecs)) {
// do something with i
}