What is a "valid range"

517 views
Skip to first unread message

David Hunter

unread,
Apr 9, 2014, 4:32:08 PM4/9/14
to std-dis...@isocpp.org
There is a discussion https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/M3MfGtYMGyY on the "Future Proposals" group which started out suggesting a vector::end_data method to get a raw pointer to the end of a vectors data. However the discussion raised the question of what a valid range means in the standard. For instance the standard has

23.3.6.4 vector data [vector.data]
    T* data() noexcept;
    const T* data() const noexcept;

    Returns: A pointer such that [data(),data() + size()) is a valid range. For a non-empty vector, data() == &front().

So the question is what happens if the vector is empty. The member function must return something as it's noexcept and the standard says [data(),data() + size()) must be a valid range. Note that "valid range" does not seems to be defined anywhere in the standard. So is it reasonable for instance for data() to return a nullptr, in other words is [nullptr, nullptr + 0) a valid range? If it isn't should the implementation return some random pointer? Is the implementation free to choose whether to return a nullptr or a random pointer?

Ville Voutilainen

unread,
Apr 9, 2014, 4:38:53 PM4/9/14
to std-dis...@isocpp.org
On 9 April 2014 23:32, David Hunter <davidh...@gmail.com> wrote:
> + size()) must be a valid range. Note that "valid range" does not seems to
> be defined anywhere in the standard. So is it reasonable for instance for

[iterator.requirements.general]/7:

"Most of the library's algorithmic templates that operate on data
structures have interfaces that use ranges.
A range is a pair of iterators that designate the beginning and end of
the computation. A range [i,i) is an
empty range; in general, a range [i,j) refers to the elements in the
data structure starting with the element
pointed to by i and up to but not including the element pointed to by
j. Range [i,j) is valid if and only if
j is reachable from i. The result of the application of functions in
the library to invalid ranges is undefined."

The reachability is in the previous paragraph (6):
"An iterator j is called reachable from an iterator i if and only if
there is a finite sequence of applications of
the expression ++i that makes i == j. If j is reachable from i, they
refer to elements of the same sequence."


> data() to return a nullptr, in other words is [nullptr, nullptr + 0) a valid
> range? If it isn't should the implementation return some random pointer? Is
> the implementation free to choose whether to return a nullptr or a random
> pointer?


Based on those paragraphs, yes, that is a valid range, an implementation
does not need to return a random pointer, but yes, it can do so. It can return
the address of the container itself, for instance.

Nevin Liber

unread,
Apr 9, 2014, 4:42:32 PM4/9/14
to std-dis...@isocpp.org
On 9 April 2014 15:38, Ville Voutilainen <ville.vo...@gmail.com> wrote:
It can return
the address of the container itself, for instance.

If you do this, don't you have to be careful not to violate type punning rules? 
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Ville Voutilainen

unread,
Apr 9, 2014, 4:47:22 PM4/9/14
to std-dis...@isocpp.org
On 9 April 2014 23:42, Nevin Liber <ne...@eviloverlord.com> wrote:
> On 9 April 2014 15:38, Ville Voutilainen <ville.vo...@gmail.com>
> wrote:
>>
>> It can return
>> the address of the container itself, for instance.
>
>
> If you do this, don't you have to be careful not to violate type punning
> rules?


Perhaps, but for a standard-layout string, you may have a small-string
optimization
buffer as your first member so returning the address of its first
element would be the
same thing as the address of the container. :)

Giovanni Piero Deretta

unread,
Apr 10, 2014, 12:11:22 PM4/10/14
to std-dis...@isocpp.org

On Wednesday, April 9, 2014 9:42:32 PM UTC+1, Nevin ":-)" Liber wrote:
On 9 April 2014 15:38, Ville Voutilainen <ville.vo...@gmail.com> wrote:
It can return
the address of the container itself, for instance.

If you do this, don't you have to be careful not to violate type punning rules? 

Casting between pointer types is implementation defined but allowed. Type aliasing matters only when dereferencing type punned pointers.  As the range is empty, no iterator/pointer in it can be legally dereferenced.

-- gpd
Reply all
Reply to author
Forward
0 new messages