Reputation: 45
I'd like to iterate over a container (say a std::vector
) but not from the beginning. I am basically trying to replicate boost::make_iterator_range(v.begin() + 1, v.end())
.
I came up with this:
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
std::vector<int> v {1, 2, 3};
std::for_each_n(v.begin() + 1, v.size() - 1, [](auto& n)
{
std::cout << n << '\n';
});
}
However this seems like a poor solution. Also it requires C++17 while I am looking for a solution that works in C++14.
Is there a better way to achieve this without the use of third party libraries?
Upvotes: 0
Views: 127
Reputation: 238301
Is there a better way to achieve this ...
A solution using ranges (courtesy of cigien in comments):
for (int element : v | ranges::drop_view(1))
A solution using span
for (int element : span(&v[1], v.size() - 1))
Of course, there aren't std::ranges
nor std::span
until C++20, so unless you want to use a third party implementation, you'll need to write your own.
If you don't want to implement your own libraries, nor can use C++20, nor want to use a third party library, then std::for_each
an alternative that is in C++11.
Upvotes: 2
Reputation: 12928
To replicate make_iterator_range
you need an object with a begin
and end
function. Something like this.
template <typename T>
struct iterator_range {
iterator_range(T begin, T end) : m_begin(begin), m_end(end) {}
T begin() {
return m_begin;
}
T end() {
return m_end;
}
T m_begin, m_end;
};
Then we can make our make_iterator_range
function that return an iterator_range
.
#include <vector>
#include <iostream>
template <typename T>
struct iterator_range {
iterator_range(T begin, T end) : m_begin(begin), m_end(end) {}
T begin() {
return m_begin;
}
T end() {
return m_end;
}
T m_begin, m_end;
};
template <typename T>
auto make_iterator_range(T begin, T end) {
return iterator_range<T>(begin, end);
}
int main()
{
std::vector<int> v {1, 2, 3};
auto range = iterator_range<decltype(v.begin())>(v.begin() + 1, v.end());
for (auto& i : range) {
std::cout << i << '\n';
}
for (auto& i : make_iterator_range(v.begin() + 1, v.end())) {
std::cout << i << '\n';
}
}
Upvotes: 2
Reputation: 5075
std::for_each
is in C++11 and with that you can do:
std::for_each(v.begin() + 1, v.end(), [](auto &n) { ... });
Upvotes: 2