Boost logo

Boost :

Subject: Re: [boost] [range] strange behavior of operator== with iterator_range
From: Neil Groves (neil_at_[hidden])
Date: 2011-05-18 19:22:23


On Wed, May 18, 2011 at 9:25 PM, Bryce Lelbach <blelbach_at_[hidden]> wrote:
Can someone tell me if the behavior demonstrated in the following program is
intentional or a bug in Boost.Range?

The short answer - intended!

The long answer. Literal strings are not supported directly as ranges
excepted when adapted by using the as_literal function. The supported types
are listed here:
http://www.boost.org/doc/libs/1_46_1/libs/range/doc/html/range/reference/overview.html
The literal string you are testing against is an array of chars of length 4.
This array is including the null-terminator. The length of std::string does
not include a null-terminator.

The following is your code with my comments added.

#include <iostream>
#include <string>
#include <boost/range/iterator_range.hpp>

typedef boost::iterator_range<char const*> range_type;

int main (void) {
  char const* foo = "foo";

  {
    range_type r(foo, foo + 3);

    std::cout << r << std::endl;

// <NeilGroves>
// std::string("foo") has length 3 and content is equal, hence the
// correct branch is taken.
// </NeilGroves>

    if (r == std::string("foo"))
      std::cout << "success\n"; // branch taken
    else
      std::cout << "failure\n";

// <NeilGroves>
// "foo" has type char[4] and therefore has length 4. Since the lengths
// are not equal they are not equal.
// </NeilGroves>

    if (r == "foo")
      std::cout << "success\n";
    else
      std::cout << "failure\n"; // branch taken
  }

  {
    range_type r(foo, foo + 4);

    std::cout << r << std::endl;

// <NeilGroves>
// Now r has length 4 and std::string("foo") has length 3, correct branch
taken
// </NeilGroves>
    if (r == std::string("foo"))
      std::cout << "success\n";
    else
      std::cout << "failure\n"; // branch taken

// <NeilGroves>
// "foo" has type char[4] and r is now of length 4 hence the correct branch
is taken
// </NeilGroves>
    if (r == "foo")
      std::cout << "success\n"; // branch taken
    else
      std::cout << "failure\n";
  }
}

--
Bryce Lelbach aka wash
boost-spirit.com
px.cct.lsu.edu
github.com/lll-project
Literal strings are no longer intended to work as ranges. Literal string
interoperability is provided via the as_literal function (
http://www.boost.org/doc/libs/1_46_1/libs/range/doc/html/range/reference/concept_implementation/semantics/functions.html).
Unfortunately it is not possible to stop this example compiling without
breaking other valid uses of char arrays, since I cannot distinguish between
a block of char, and a null-terminated string array. Boost.Range always
interprets a char array as a block of chars and not as a null-terminated
string.
I hope this helps.
Regards,
Neil Groves

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk