Re: Why is this code complaining about constness?
On Aug 2, 9:30 pm, markscottwright <markscottwri...@gmail.com> wrote:
On Aug 2, 4:23 am, James Kanze <james.ka...@gmail.com> wrote:
On Aug 1, 8:10 pm, markscottwright <markscottwri...@gmail.com> wrote:
I'm using visual studio 8, and the following code is failing. For the
life of me, I can't see what's wrong...
void myTest(std::string const& in)
{
using namespace std;
string::const_iterator lastNonWhitespace = find_if(in.rbegin(),
in.rend(), not1(ptr_fun(isspace)));
Victor has pointed out one of the errors. But the last argument
to find_if can't be correct either. First, of course, because
one of the isspace functions is a template, so argument type
deduction fails if it is visible. (Of course, the one that it a
template takes two arguments, so can't be used here. But the
compiler can't know that until it's instantiated the template,
and it can't instantiate the template until it has chosen the
correct isspace.) And secondly, because calling the one
argument version of isspace (from <cctype> or <ctype.h>) with
the char resulting from the referencing of
std::string::const_reverse_iterator is undefined behavior.
}
C++. Sigh.
Don't blame C++ for this one. We just inherited it from C:-).
So, what *is* the correct way to find the last non-whitespace
character in a string?
As usual, there is no one correct way. A lot depends on
context. I do a fair amount of text processing from time to
time, so I've written library classes to wrap the functions in
<locale>, particularly those in the ctype facet. For a one time
use, however, that's a lot more than you'd probably want to
type; if internationalization isn't an issue (or if you're happy
to always use the global locale), then just writting something
like:
struct IsWhite
{
bool operator()( char ch ) const
{
return isspace( static_cast< unsigned char >( ch ) ) ;
}
} ;
and using it as your predicate (possibly with std::not1), should
be largely sufficient.
Officially, of course, you're supposed to use the std::ctype
facet defined in <local>. But everything in <local> is pretty
much a horror with regards to ease of use, so unless you really
need full internationalization, something like the above is much
simpler, and just as good. Just remember to cast any char to
unsigned char before invoking any function in
<ctype.h>/<cctype>, and you should be OK.
And also: be wary of passing the address of a function to a
template function (e.g. as predicate or functional object).
Type deduction and function overload resolution don't always
work very well in such cases: basically, type deduction needs to
know the results of function overload resolution, and vice
versa, so the compiler gives up, and says ambiguous. This is
especially true in cases like the above, because the overloaded
functions are found in <locale>, which may or may not be
indirectly included. It's a bit of a pain to have to write
small classes like the above, but it avoids problems in the long
run.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34