Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does boost::find_first take a non-const reference to its input?

Tags:

c++

string

boost

Boost's find_first algorithm is a souped-up equivalent of C's strstr(), but why does the haystack — the search space — get passed in as a non-const reference? The matching range is returned in a separate iterator_range object, so it's not a matter of output-by-reference.

It prevents invocation with a temporary range created by make_iterator_range.

const std::string str("haystack");
const std::string findstr("stack");

boost::sub_range<const std::string> match = boost::algorithm::find_first(
        boost::make_iterator_range(str),
        boost::make_iterator_range(findstr));

Instead, a local variable representing the source range must be created explicitly:

const std::string str("haystack");
const std::string findstr("stack");

boost::sub_range<const std::string> haystack = boost::make_iterator_range(str);

boost::sub_range<const std::string> match = boost::algorithm::find_first(
        haystack,
        boost::make_iterator_range(findstr));

(This applies equally to the other functions in boost/algorithm/string/find.hpp, ie. find, ifind_first, find_last, ifind_last, find_nth, ifind_nth, find_head, find_tail & find_token).

like image 869
Ted Percival Avatar asked Nov 21 '12 18:11

Ted Percival


1 Answers

It's to ensure that the returned range is still valid after the call to find_first.

While the initial case above would be fine, the following would result in a match that points to a destroyed temporary string:

boost::sub_range<const std::string> match = boost::algorithm::find_first(
        boost::make_iterator_range(std::string("haystack"),
        boost::make_iterator_range(std::string("stack"));

The requirement that the haystack be non-const prevents it binding to a temporary object (rvalue) which is destroyed upon find_first's return and invalidates the match's iterators.

like image 52
Ted Percival Avatar answered Sep 28 '22 07:09

Ted Percival