tags:

views:

233

answers:

7

found this typo recently

 if (name.find('/' != string::npos))

I was amazed that it even compiles at -Wall -Werror (didnt try with -pedantic)

so coffee quiz - does it eval to true or false

edit : answer - true

string::npos -> inta (usually -1)
'/' -> intb
inta != intb -> bool true
bool true-> int = 1 (probably) -> char 0x01
name.find(0x01) returns  string::npos (probably , certainly in my case)
string::npos -> int (usually -1 certainly !0) -> true

the dev meant

if(name.find('/') != string::npos)
A: 

I'd say false, unless name contains a char with value 0x01.

jdv
A: 

It depends on if name starts with a char equal to 1.

You shouldn't be amazed it compiles, there's nothing wrong about it. '/' != std::string:npos evaluates to true, and the only overload of find that would work is the char c, size_t pos version, as bool can be converted to an integer 1.

So now we're looking for (char)1, and what that returns depends on the string. If it starts with (char)1, it returns 0 and that's false. In any other case, it returns a non-zero integer, or true.

GMan
`name` doesn't need to _start_ with 1. It just has to include it somewhere in the string.
wilhelmtell
@wilhelmtell: How so? If it starts with it, it returns 0. Otherwise it returns a positive integer.
GMan
@GMan if `name` doesn't include 1 then `string::find()` returns a negative integer.
wilhelmtell
Oh wait. As a `size_t` it's still positive. :s I'll just go ... there ... at the corner ... if anyone needs me.
wilhelmtell
@wilhelmtell: <3
GMan
A: 

I'm surprised the implicit cast from bool to char doesn't emit a warning... as far as I can tell, it'll return true unless name begins with '\001'.

+1  A: 

'/' != string::npos evaluates to true. true is promoted to int (value = 1). find probably doesn't find a value of 1. if expression probably returns string::npos, which is typically -1, which is not zero, and is therefore true. My guess: true.

jwismar
there's no overload of string::find that takes an int. there's one that takes a char and an optional size. there are also a couple that take a pointer as the first parameter.
wilhelmtell
A: 

It will evaluate to true if name contains a char == SOH

otherwise false

hhafez
+1  A: 

'/' doesn't equal string::npos since npos is required to be negative, and none of the characters in the basic execution character set is allowed to be negative. Therefore, it's going to look for a value of 1 in the string (presumably a string anyway) represented by name. That's a pretty unusual value to have in a string, so it's usually not going to find it, which means it'll return std::string::npos, which will convert to true.

Edit: as Johannes pointed out, although the value assigned to npos must be negative 1 (as per 21.3/6) that's being assigned to a size_type, which must be unsigned, so the result won't be negative. This wouldn't normally make any real difference though -- the '/' would be compared to npos using unsigned arithmetic, so the only way they could have the same value would be if 1) '/' was encoded as -1 (not allowed as above) or char had the same range as size_type.

In theory, the standard allows char to have the same range as other integral types. In fact, quite a bit of I/O depends on EOF having a value that couldn't originate from the file, which basically translates to a requirement that char have a range that's smaller than int, not just smaller than or equal to (as the standard directly requires).

That does leave one loophole, though it's one that would generally be quite horrible: that char and short have the same range, size_type is the same as unsigned short, and int has a greater range than char/short. Giving char and short the same range wouldn't be all that horrible, but restricting size_type to the same range as short normally would be -- in a typical case, short is 16 bits, so it would restrict containers to 64K. That kind of restriction was problematic 20 years ago under MS-DOS; it simply wouldn't be accepted in most markets today.

Jerry Coffin
"since npos is required to be negative", not true. It's required to be the highest possible (= positive) value of `size_type`.
Johannes Schaub - litb
A: 

Others have posted the correct answer already: The result of the boolean expression should be 1 (a truth value), because '/' should have a value smaller than the unsigned string::npos (defined to be the largest value a size_t can hold). Because 1 is an integer, and because 1 can't possibly be an address, the compiler finds the only overload of string::find() it can call is the one with char c, size_t pos.

But that's not the end of the story. Try to change the boolean expression from '/' != string::npos to '/' == string::npos. Now the result of the expression is 0, again an integer. Because there is no overload for string::find() that takes an int, the compiler must cast 0 -- but to what? It can cast it to a char and it can cast it to a pointer. Both are valid choices, so that's an ambiguous call.

So there you go: your code changes from a valid warning-free function call to an ambiguous function call by changing an operator from != to ==.

wilhelmtell
See the comment on the accepted answer. `npos` is not `-1`.
Johannes Schaub - litb
corrected .. and f**k those 15 chars
wilhelmtell