Reputation: 3
I just want to get an element that is in the next iteration (using range-based for loop)
I have tried something like that:
*(&x+1) is supposed to mean "i+1" if "i" would have been an iterator here
bool factorChain(std::vector<int> arr) {
for(auto& x : arr)
{
if (*(&x+1)%x != 0) return false;
}
return true;
}
I want it to work like that, but with a range-based for loop:
bool factorChain(std::vector<int> arr) {
for(int i=0; i<arr.size()-1; i++)
{
if(arr[i+1]%arr[i]!=0) return false;
}
return true;
}
or this might be more helpful:
bool factorChain(std::vector<int> arr) {
for(std::vector<int>::const_iterator iter = arr.begin();
iter != arr.end()-1; ++iter){
if(*(iter+1)%*(iter)!=0) return false;
}
return true;
}
Upvotes: 0
Views: 1203
Reputation: 275395
In general you cannot.
I have written iterators_of
, a range adapter that takes a range and reyurns a range of the iterators.
You start with a range type:
template<class It>
struct range{
It b,e;
It begin()const{return b;}
It end()const{return e;}
};
that is a minimal one.
Then an indexing iteratoroid:
template<class T>
struct indexing_iteratoid{
using this_t=indexing_iteratoid;
T t;
T operator*()const{return t;}
void operator++()&{++t;}
friend bool operator==(this_t const& lhs, this_t const& rhs){return lhs.t==rhs.t;}
friend bool operator!=(this_t const& lhs, this_t const& rhs){return lhs.t!=rhs.t;}
};
again, minimal and stripped down.
template<class R>
auto iterstors_of(R&& r){
using std::begin; using std::end;
auto b=begin(r), e=end(r);
return range{ indexing_iteratoid{ b }, indexing_iteratoid{ e } };
}
and now you can:
for(auto it:iterators_of( vec ) ){
}
and *it
is an element, and *std::next(it)
is the next element (care not to go over the end), etc.
Code is based off code that works, but this was typed on a phone and probabky has tpyos.
It is an iteratoid because it isn't an iterator; it just qualifies for for(:)
loops.
It is indexing, because its primary use is to store size_t's: pass it 0
and r.size()
and you count from 0
to size()-1
.
Upvotes: 0
Reputation: 52471
If you are really bent on using range-based loop, you can do something like this:
bool factorChain(std::vector<int> arr) {
int* prev = nullptr;
for(auto& x : arr)
{
if (prev && x % *prev != 0) return false;
prev = &x;
}
return true;
}
However, at this point it's likely clearer, more readable to just spell out an iterator-based or index-based loop, than to try and salvage range-based one.
Now, for extra subtlety points, how about something like this:
bool factorChain(std::vector<int> arr) {
return std::adjacent_find(arr.begin(), arr.end(),
[](int prev, int next) { return next % prev != 0; })
== arr.end();
}
Upvotes: 4
Reputation: 20579
I just want to get an element that is in the next iteration (using range-based for loop)
The answer to your question is simple: don't abuse features. The range-for loop is for the simplest case where you want to traverse the array one by one. If you want fine-grained control over the traversal, don't use the range-for loop. Your last two approaches are fine, so don't over-complicate things.
By the way, arr
should be passed by const reference to avoid unnecessary copy.
Upvotes: 1