count_if(somestr.begin(), somestr.end(), isalpha) fails to compile ongcc, but compiles on VS2008

R

rep_movsd

Ideally the predicate passed to count_if should be of the form:

bool pred(char &ch)

I think...

For some reason VC 2008 accepts isalpha even though it takes an int
and returns an int.

What is the right behavior according to the standard?

V
 
F

Francesco

Ideally the predicate passed to count_if should be of the form:

bool pred(char &ch)

I think...

For some reason VC 2008 accepts isalpha even though it takes an int
and returns an int.

What is the right behavior according to the standard?

V

I know that I should shut up, since I've almost no grip about the
standard and about the way compilers actually work, nonetheless I'd
like to give my point of view, just to check if I'm starting to get
such things right or not, thereafter we'll both have to wait for more
knowledgeable advice coming from someone else.

You're allowed to feed a char to isalpha and transform its result to a
bool:

-------
char ch = 'A';
bool res = isalpha(ch);
-------

The standard explicitly allows "int -> bool" conversion and "char ->
int" promotion, so far so good.

But when you're feeding isalpha to count_if, the compiler might
interpret it as a "int -> char" demotion and might not accept it - at
least that's my impression.

The odd part is that gcc accepts the following without issuing any
warning:

-------
int i = 1500;
char ch = i;
-------

I wasn't able to find any clause allowing such operation in the
standard.

In any case, your code can be made to compile (in gcc) by wrapping
isalpha inside a "bool f(char&)" function and passing this new
function to count_if, although I'm sure you didn't need to be told
this.

For what they could be worth, those were my two cents.

Cheers,
Francesco.
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
Ideally the predicate passed to count_if should be of the form:

bool pred(char &ch)

I think...

For some reason VC 2008 accepts isalpha even though it takes an int
and returns an int.

What is the right behavior according to the standard?

There are two requirements:

1) The element must implicitly convert to the argument type.
2) The return from the predicate must implicitly convert to bool.

Since there are implicit conversions from char to int and from int to
bool, isalpha should work.
 
F

Francesco

Francesco said:
The odd part is that gcc accepts the following without issuing any
warning:
I wasn't able to find any clause allowing such operation in the
standard.

It's a standard conversion. See [conv.integral].

--
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

Thank you for your pointer, Pete.

I've read that section in this version:
http://www.csci.csusb.edu/dick/c++std/cd2/conv.html

Which is really outdated (1996).

If I can abuse of your time further, could you check that version and
point me out which clause - if any - covers "char to int" conversion?

As I see it, it could be 4.7.1., but more recent versions could be
more explicit - unfortunately, as I mentioned elsewhere, I'm not able
to get more recent versions because those PDF files are too large for
my Internet connection. I'll take the chance to ask whether somebody
can point me to an HTML version of some of the latest drafts,
something like the link I posted above.

In any case, I think the compiler should issue a warning about a
possible truncation, but maybe the standard already mandates it and my
gcc compiler is simply outdated.

Thanks a lot for your patience,
Francesco
 
A

Alf P. Steinbach

* Pete Becker:
rep_movsd said:
[subject line] count_if(somestr.begin(), somestr.end(), isalpha)
fails to compile on gcc, but compiles on VS2008 [/subject line]


Ideally the predicate passed to count_if should be of the form:

bool pred(char &ch)

I think...

Surely that should be

bool pred(const char&)

Or, more simply,

bool pred(char)
For some reason VC 2008 accepts isalpha even though it takes an int
and returns an int.

What is the right behavior according to the standard?

rep_movsd: please learn to place your question in the main article text.

I didn't read it until I saw Pete's reply, when I made an effort to find out
what the heck you were asking.

That involved displaying your article's headers.

In fact what's required is that the predicate can be called with an
argument of type char and that it returns a type that can be converted
to bool. Whenever you're dealing with predicates or other things that
get passed to templates, think in terms of how the thing will be called,
not in terms of how it has to be written. So, for example, find_if will
typically use the predicate like this:

if (pred(*iter))

where *iter has type char or maybe cv char&, depending on where iter
came from. isalpha(*iter) works just fine in an if statement.

Uh, AFAIK ::isalpha, from the C library, can't portably be called with 'char'
actual argument.

But it can be wrapped like

bool isAlpha( char c ) { return !!::isalpha( (unsigned char)c ); }


Cheers,

- Alf
 
A

Alf P. Steinbach

* Pete Becker:
Which is why it should have been raised in a reply to the original message.

But you didn't.

I answered a specific question.

(you'd not want

It's not leading anyone astray to answer the question they asked.

so, you didn't think of it.

Ah, I see. You know better than I do what it is that I'm thinking.

No, I just refuse to believe, in spite of your childish behavior e.g. below and
before, that you'd actively mislead novices.

And so I choose to believe that you just didn't see the point I raised above.

Even when you, with utter disregard for what that implies, protest.


Pete, this is the second time in just as many months that you "plonk" me,
putting me in your killfilter whence, presumably, you won't see my articles.

This time you "plonk" me for pointing out something that for whatever reason you
didn't see when you wrote your article (even though you're now protesting,
implying that you /chose/ to mislead the OP, which is just silly), and last time
you plonked me for asking what you meant by a rather dubious statement.

It's very childish behavior you exhibit this way, please stop.


Cheers,

- Alf
 
V

Vaclav Haisman

rep_movsd wrote, On 15.8.2009 16:51:
Ideally the predicate passed to count_if should be of the form:

bool pred(char &ch)

I think...

For some reason VC 2008 accepts isalpha even though it takes an int
and returns an int.

What is the right behavior according to the standard?

V
You need to provide more context, e.g. what does GCC say when it fails to
compile your code. My guess is that you use using namespace std; and that you
see something like "error: no matching function for call to
‘count_if(string::iterator, string::iterator, <unresolved overloaded function
type>)’". If that is the error, you can use
"static_cast<int(*)(int)>(isalpha)" as the third argument, it will force GCC
to resolve the overloads to int std::isalpha(int) from <cctype>.
 
A

Alf P. Steinbach

* Vaclav Haisman:
rep_movsd wrote, On 15.8.2009 16:51:
You need to provide more context, e.g. what does GCC say when it fails to
compile your code. My guess is that you use using namespace std; and that you
see something like "error: no matching function for call to
‘count_if(string::iterator, string::iterator, <unresolved overloaded function
type>)’". If that is the error, you can use
"static_cast<int(*)(int)>(isalpha)" as the third argument, it will force GCC
to resolve the overloads to int std::isalpha(int) from <cctype>.

Except that, as discussed else-thread, it isn't really a good idea to use that
function directly, since it expects an argument that either is non-negative or
is EOF.

With a signed char type, which is the default with most compilers, directly
using a char as actual argument can easily break the function's assumptions.

Happily it's easy to wrap this function.


Cheers,

- Alf
 
J

James Kanze

(e-mail address removed)>, (e-mail address removed)
says...
There are two requirements:
1) The element must implicitly convert to the argument type.
2) The return from the predicate must implicitly convert to bool.
Since there are implicit conversions from char to int and from
int to bool, isalpha should work.

It's significantly more complex than that. At the syntax level,
std::count_if doesn't take a bool pred(char&), or anything like
that---it takes a Predicate, which is a template parameter; the
type must thus be deduced by the compiler. If the only function
isalpha visible is the one in <ctype.h>, then that's what the
compiler will use, and it will deduce that Predicate has type
int (*)( int ). Depending on the context, however, it's quite
likely that the std::isalpha in <locale> is also visible---since
that's a function template, the compiler doesn't know its type,
so template type deduction fails. And whether <locale> has been
included or not may depend on the implementation; an
implementation can (but is not required to) include <locale> in
any other standard header. Given that his code works with one
compiler, and not with another, I'd guess that this is the
issue; it can be solved by using ::isalpha (assuming that he did
include <ctype.h>, and not <cctype>).

Of course, all this does is make the code compile. The isalpha
in <ctype.h> may result in undefined behavior if called with a
char; what he really wants is the isalpha in <locale> (which
does work with char). Which can "easily" be called with
something like:
std::count_if(
c.begin(), c.end(),
std::bind2nd(
static_cast< bool (*)( char, std::locale const& ) >(
&std::isalpha ),
std::locale() ) ) ;
(I'm not actually sure, of course. I've got a couple of generic
functional objects which I use in such cases. Makes life a lot
easier. And of course, in more recent code, everything is
UTF-8, which requires slightly different tactics.)
 
J

James Kanze

rep_movsd wrote:
In fact what's required is that the predicate can be called
with an argument of type char and that it returns a type that
can be converted to bool. Whenever you're dealing with
predicates or other things that get passed to templates, think
in terms of how the thing will be called, not in terms of how
it has to be written. So, for example, find_if will typically
use the predicate like this:
if (pred(*iter))
where *iter has type char or maybe cv char&, depending on
where iter came from. isalpha(*iter) works just fine in an if
statement.

For what definition of "works just fine"? Compiles just fine,
yes. But in the contexts I usually work in (Solaris, Linux,
Windows, with plain char 8 bit signed), the only isalpha
function I know which can be called with a single argument
results in undefined behavior if I call it with char.

And of course, counting on template type deduction working when
passing this function as a predicate to one of the standard
algorithms is probably being optimistic as well, since there's
also an isalpha function template in one of the standard
headers.
 
F

Francesco

The conversion here is int to char.

Yes, of course, I just mistyped it and it was easy to guess.
Well, 4.7/1. Paragraph numbers don't get dots. And the key here is
paragraphs 2 and 3.

It's sort of nitpicking to my eyes, maybe the latest standards mandate
that their paragraphs get referenced using the slash - matter of
customs and of changed minds - but in this version:
http://www.csci.csusb.edu/dick/c++std/cd2/diff.html
paragraph numbers get the dot.

In any case, you were able to understand what I meant and that's
enough for the sake of communication.
, but more recent versions could be


How much more explicit do you want it to be?

        If the destination type is unsigned, the resulting value
        is the least unsigned integer congruent to the source
        integer (modulo 2n where n is the number of bits used
        to represent the unsigned type). ....

        If the destination type is signed, the value is
        unchanged if it can be represented in the destination
        type (and bit-field width); otherwise, the value is
        implementation-defined.

Assume char is 8 bits.

In your example, if char is unsigned, the result of the conversion is
the value (1500) modulo 256.

If char is signed, the value can't be represented, so the result is
implementation defined. Check your compiler's documentation to see what
it does.

Fine, in my mind I assumed that conversions did not involve losing
data, and actually I wasn't able to fully understand those paragraphs,
as it seems - sorry, I didn't mean to add unneeded traffic to this
stream, but at least I'm continuing to learn new things.
The standard never requires warnings. Some compilers warn about
conversions like this. Many people find such warnings annoying.

I'll have to get a better grip on the standard before dropping in into
such topics again.

My heartfelt apologies.

Have good time,
Francesco
 
R

rep_movsd

Thanks for the lively and divergent discussion...

#include'ing ctype.h and using ::isalpha gets it to compile.

I heed the advice that using isalpha on chars is not right anyway.

Thanks once again
 
F

Francesco

Somebody wrote some HTML stuff. <g> That's not the standard, and it's
not a product of the standards committee.

You're right, I thought that that page was part of the standard and I
was wrong.
Well, sure. But there are cases where using a dot would indicate a
subsection when it was meant to refer to a paragraph.

Agreed, the next time I'll have to cite the standard I'll use the
following form: "4.7 [conv.integral] paragraph 1", just like the
standard does.

As I just realized, yours wasn't a nitpick at all, it was an important
point because using the dot for the paragraphs could lead to
misunderstandings, thanks a lot for correcting my mistake.

Best regards,
Francesco
 
F

Francesco

You're right, I thought that that page was part of the standard and I
was wrong.

Uhm, actually, the problem there is that I mistakenly read it as if it
cited paragraphs using the dot, which it doesn't.

About whether that page reports a past product of the standard
committee or not I'm not really sure right now - speaking about the
content, not about the medium.

Never mind.
 
J

James Kanze

On 16 Ago, 17:17, Pete Becker <[email protected]> wrote:
As I just realized, yours wasn't a nitpick at all, it was an
important point because using the dot for the paragraphs could
lead to misunderstandings, thanks a lot for correcting my
mistake.

There isn't a dicotomy between nitpicking and important points.
Pete's remark was simply meant to help you---if you use a point
for the paragraph, something like 5.4 is ambiguous. The general
convention among people working on the standard is to use 5/4
for the fourth paragraph of section 5 (one of the more
frequently cited paragraphs in the standard), and 5.4 for the
"Explicit type conversion (cast notation)" section. (Of course,
within the committee, it is preferred to use the labels for
sections, e.g. [expr]/4 or [expr.cast], since section numbers
tend to change between drafts.)
 
F

Francesco

As I just realized, yours wasn't a nitpick at all, it was an
important point because using the dot for the paragraphs could
lead to misunderstandings, thanks a lot for correcting my
mistake.

There isn't a dicotomy between nitpicking and important points.
Pete's remark was simply meant to help you---if you use a point
for the paragraph, something like 5.4 is ambiguous. The general
convention among people working on the standard is to use 5/4
for the fourth paragraph of section 5 (one of the more
frequently cited paragraphs in the standard), and 5.4 for the
"Explicit type conversion (cast notation)" section. (Of course,
within the committee, it is preferred to use the labels for
sections, e.g. [expr]/4 or [expr.cast], since section numbers
tend to change between drafts.)

Well, it's my turn to be nitpicking, or maybe not.

Feeding this string to Google:
define:nitpick

I get:
be overly critical; criticize minor details
wordnetweb.princeton.edu/perl/webwn

While feeding:
define:dichotomy

I get:
being twofold; a classification into two opposed parts or subclasses;
"the dichotomy between eastern and western culture"
wordnetweb.princeton.edu/perl/webwn

Hence, as I see it, telling you that you spelled the word "dichotomy"
in the wrong way I would be nitpicking. That is, I would be correcting
you in the right way, but that would be about a minor, unimportant
detail that rises no misunderstanding.

That's the inverse with the dot/slash point. As I've seen it before,
it was a minor detail, but Pete has shown me that it was a major
detail, that is, an important point that could lead to
misunderstandings.

I hope you agree with me that "minor" and "major" represent a
dichotomy, just like "nitpicking" and "remarking an important point"
do.

The rest of your post doesn't add anything, really, as you can see
from the text you cited from my post: I've agreed to the point, I've
recognized that he was just trying to help me and I thanked him for
doing it.

Which is kind of an unusual behavior in these threads, I must remark.

I hope these posts won't dive into further nitpicking polemics, such
as the fact that you compared a verb with a substantive or about the
fact that I forgot to put a verb in the text you cited, offering an
undefended side to such criticism.

Francesco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top