I'm having some trouble solving an issue in my program. So currently each chunk will return an iterator, but the iterator depends on two cases:
the desired element is found in the chunk: return resultIter;
the desired element is not found in the chunk: 'return nullptr`
the first case is simple enough and easy to solve, but the second case is where I am running into trouble. Given a template argument InIter
, how can I convert a nullptr
into the InIter
category?
template< typename InIter, ...>
InInter func(...) {
InIter res = //returns iter to found element if found
loop(...) //if so a token will changed to signify a cancelation
if(token.was_cancelled())
return res; //easy enough
return nullptr; //doesn't work
}
which gives me this error:
'nullptr': all return expressions in a lambda must have the same type: previously it was 'test::test_iterator'
it makes sense, I can't suddenly switch up return types in the middle of a lambda function, but I don't know how to solve this. note the code about is a very simplified version of the issue at hand, in it's actual implementation it is inside a lambda and part of a much bigger function call. However this is the only relevant portion
i've also tried:
return InIter(nullptr);
return (InIter)(nullptr);
return NULL;
return InIter(NULL);
...
Of course none of these work. there as to be an easy way to do this I just am not seeing?
The expected pattern for using iterators, is that if you want to report that you found no match, you would return the iterator that points to the end of your sequence.
So if you called:
InIter res = find_an_iterator_meeting_an_interesting_condition(begin, end);
and it found no match, you would return end
. The caller would be responsible for checking that condition.
There are two approaches.
First, the standard approach, is that when working with iterators, you are actually working with a range of iterators (from a begin
, to an end
).
In that case, failure to find something would consist of returning end
.
In some extreme corner cases this isn't the right thing to do (imagine if you ask "where is the right place to insert Y? And the answer isn't "at the end of the sequence" but rather "somewhere completely different")
In that case, something like boost::optional
is the right answer -- your function returns an optional<Iterator>
. Then you can return a nullopt
to mean "no answer is valid", and an iterator if an answer is valid.
There are proposals to bring in an optional
to C++ in C++14.
A "poor man's optional" is a std::pair<bool, Iterator>
, where you ignore the .second
's value if the .first
is false
. If you have no access to boost
, I'd advise reimplementing optional
rather than using this technique.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With