Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over a single lvalue

I'd like to pass a single lvalue to a function which expects a pair of iterators, and for it to act as if I'd passed a pair of iterators to a range containing just this value.

My approach is as follows:

#include <iostream>
#include <vector>

template<typename Iter>
void iterate_over(Iter begin, Iter end){
    for(auto i = begin; i != end; ++i){
        std::cout << *i << std::endl;
    }
}

int main(){
    std::vector<int> a{1,2,3,4};
    iterate_over(a.cbegin(), a.cend());

    int b = 5;
    iterate_over(&b, std::next(&b));
}

This appears to work correctly in g++5.2, but I'm wondering if this is actually defined behaviour and if there are any potential issues?

like image 503
cloakedlearning Avatar asked Jul 18 '16 16:07

cloakedlearning


1 Answers

Yes this is defined behavior. First we have from [expr.add]/4

For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

So a single object is treated as a array of length 1. Then we have [expr.add]/5

[...]Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

Emphasis mine

So since the first array element is also the last array element, and adding 1 to the last array element gives you the one past the object, it is legal.

like image 175
NathanOliver Avatar answered Nov 14 '22 21:11

NathanOliver