Search code examples
c++syntaxtype-safety

C++ STL: Trouble with iterators


I'm having a beginner problem:

bool _isPalindrome(const string& str)
{
    return _isPalindrome(str.begin(), str.end()); // won't compile
}

bool _isPalindrome(string::iterator begin, string::iterator end)
{
    return begin == end || *begin == *end && _isPalindrome(++begin, --end);
}

What am I doing wrong here? Why doesn't str.begin() get type checked to be a string::iterator?

Update: Better version:

bool BrittlePalindrome::_isPalindrome(string::const_iterator begin, string::const_iterator end)
{
    return begin >= end || *begin == *(end - 1) && _isPalindrome(++begin, --end);
}

Solution

  • Assuming that you have a declaration of the second function before the first function, the main issue is that you are passing the strings by const reference.

    This means that the only overloads of begin() and end() that you have access to are the const versions which return std::string::const_iterator and not std::string::iterator.

    The convention for iterators is that the end iterator points one beyond the end of a range and is not dereferencable - certainly if you pass str.end() as the end parameter. This means that *begin == *end is not valid, you need to decrement end once first. You are also going to have an issue with ranges with odd numbers of elements. By doing ++begin and --end with no further checking your iterators may cross over in the recursion rather than triggering the begin == end condition.

    Also note that for maximum portability, global identifiers shouldn't start with an underscore.