Skip to content
This repository was archived by the owner on Jul 3, 2024. It is now read-only.
This repository was archived by the owner on Jul 3, 2024. It is now read-only.

How do I properly dereference an iterator? #94

@davidwin

Description

@davidwin

The -Wlifetime project is intriguing, but there are still too many false positives in real-world projects I have tested it on. One thing I quite haven't understood is how to treat iterators in order not to trigger null dereference warnings. Very often in generic iterator code, you don't compare an iterator against a null value before dereferencing it, but against the end of a range. Do I need to annotate iterator code in any way to avoid diagnostics? For instance, consider this silly function that just returns the value of the first integer in a range or zero if the range is empty:

template<typename It>
int check(It begin, It end)
{
    return begin < end ? *begin : 0;
}
...
// Called from somewhere
std::array x { 1, 2, 3 };
int y = check(x.begin(), x.end());

This results in the following diagnostics:

warning: dereferencing a possibly null pointer [-Wlifetime-null]
    return begin < end ? *begin : 0;
                         ^~~~~~
note: in instantiation of function template specialization 'check<int *>' requested here
    return check(x.begin(), x.end());
           ^
note: the parameter is assumed to be potentially null. Consider using gsl::not_null<>, a reference instead of a pointer or an assert() to explicitly remove null
int check(It begin, It end)
          ^~~~~~~~

Now, not_null<> doesn't feel like a good option here, and depending on the iterator, it can't be checked against null before dereferencing. In the case of std::array, this would work:

template<typename It>
int check(It begin, It end)
{
    return begin && begin < end ? *begin : 0;
}

It doesn't look like ideomatic iterator code, though. And it wouldn't compile if std::vector iterators were used. Comparing against a default constructed iterator technically works for some more iterator types, but it doesn't remove the -Wlifetime-null diagnostic for std::vector iterators. See an example here: https://godbolt.org/z/aUCm3D

I suppose that I have missed something fundamental here. I would like to be reminded if I dereference an iterator with comparing it to something, but sometimes and end iterator is the "null value".

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions