hi all,

i tried this code, but it doesnt work, it says vector subscript out of range:

(sorry, i just dont understand how to correctly post code, if someone could tell me, please?)

#include <iostream>
#include <vector>

using namespace std;

vector<int> v;
v.push_back(1); v.push_back(2);

if (2 < v.size() && v[2] == 3) cout << "doesnt work.";

i understand why it doesnt work, v[2] doesnt exist. my question is: is there an easier way to check the two conditions than do it one after the other in two different (perhaps nested) if-statements, so that the non-existence of v[2] is checked before it can generate an error?

cheers,
richard

Good question.

Place the code between code tags, like this: [ code] here [ /code]

(without the spaces between the brackets and the words)

Edited 6 Years Ago by daviddoria: n/a

I thought that C++ has short-circuit condition checker... Could you try if(v.size()>2 && v[2]==3) to see if it works? Not sure if the 2<v.size() is the problem.

Sorry didn't see other replies. But now can someone tell me how to delete a post? ;-D

Edited 6 Years Ago by AkashL: n/a

bubacke I just tried your code and didn't get the output 'doesnt work'. Isn't that what you wanted? I.e. Short circuit checking (ref Taywin) seems to work in vs2005 with the code in its current form.

@AkashL
His/Her code would not output 'doesnt work' because the condition is not met (the number 2 is not less than the current vector size which is 2). If his/her code generates 'out of range', it means that the result from the first condition of the code (2<v.size()) is ignored and that the second part is executed. As a result, he/she gets the 'out of range' error. Yes, maybe we need to know what compiler he/she is using and how he/she gets the error.

Could you try if(v.size()>2 && v[2]==3)

This will produce an error *again* if size of v is less than 2, as the condition(v[2]==3) will be processed anyway.
The only way I can think of now is:

if((v.size()>2)?v[2]==3:false)

@nbaztec
I get what you mean. But if an error occurs with the condition I gave above, it means that the short-circuit does not kick in. The way your condition would be equivalent to a long version as followed:

if (v.size()>2) {
   if(v[2]==3) {
     cout << "doesn't work"
   }
 }

But if an error occurs with the condition I gave above, it means that the short-circuit does not kick in.

You mean this : if(v.size()>2 && v[2]==3)
No, the conditions though evaluated separately but form a unified condition of if() hence to evaluate the insides of parenthesis both the conditions joined by && would be evaluated. So, if size()<2 & it attempts to check for v[2] then it will throw an exception, unless you subside it with try-catch.

he way your condition would be equivalent to a long version as followed:

Ternary operator has been found to be faster on many compilers.

I guess I am away from C++ too long. I thought that C++ short-circuit would stop when the first condition is not met. In this case, v.size()>2 is false and that C++ should not evaluate the second part because of the and operator. But if this is caught at compile time, then the solution I gave is wrong because it is for runtime checking.

I agree that ternary is faster but I just want to be more clear in the expression.

If I remember the C++ programming language book correctly the standard states that the second expression should not be evaluated if the first evaluates to false(would be pointless)... but maybe the OP's compiler doesn't follow this standard strictly.. or I am remembering wrong and it's not actually in the standard.

In any case, consider this (maybe the OP should try this code):

#include <iostream>
using std::cout;

bool returnTrue ( ) { cout << "ret TRUE\n"; return true; }
bool returnFalse( ) { cout << "ret FALSE\n"; return false; }

int main()
{
    if( returnTrue() && returnFalse() )
        cout << "toot\n";

    if( returnFalse() && returnTrue() )
        cout << "toot\n";
}

OUTPUT (for me):

ret TRUE
ret FALSE
ret FALSE

So in the second case, the returnTrue is not evaluated.

I'm not really sure why, or even how the OP's compiler emits this as ASM... if I were to look at the ASM code of what I just posted, it would call returnTrue and compare it to true, if the comparison fails there would be a JMP over the entire If-block, skipping the second comparison.
It doesn't make sense to me why the compiler would decide to evaluate both and then compare both...

Edited 6 Years Ago by thelamb: n/a

If I remember the C++ programming language book correctly the standard states that the second expression should not be evaluated if the first evaluates to true (would be pointless)

I guess you mean "if the first evaluates to false" instead?

My guess (again) in this case is that the compiler does not care what the result from comparing would be but concerns about how memory allocation is being used. In the second part of the condition, the use of memory is illegal, so the compiler does not like it and throws a tantrum (error). Again, I agree that why compiler flags it as an error if C++ use short circuit condition...

I guess you mean "if the first evaluates to false" instead?

Oeps, fixed.

On compile time it has no idea if v[2] is going to be valid or not, so if anyone has a reason why a compiler would decide to emit code that evaluates this second expression... please share.

Apologies, gentlemen. I made a mistake that I'd like to rectify. What thelamb states is true. What I earlier stated will hold true for Logical OR. I've been debugging a lot of code lately where I was forced to nest conditions like this.

if(arr[2]=='/' || arr[4]=='\')

Hence the error.

Edited 6 Years Ago by nbaztec: n/a

Yes, that makes absolute sense.

So what do we make of the OP's problem... compiler not following the standard?

Edit:
Maybe the OP should try to compile his code in 'release' mode.. with all optimizations enabled. If it still attempts to evaluate the v[2]... I would chose a different compiler ;)

Edited 6 Years Ago by thelamb: n/a

Just for the fun of it, what does the OP(or someone else) think the ouput of this snippet will be:

#include <iostream>
using std::cout;

bool returnTrue ( ) { cout << "ret TRUE\n"; return true; }
bool returnFalse( ) { cout << "ret FALSE\n"; return false; }

int main()
{
    if( returnTrue() || returnFalse() )
        cout << "toot\n";
}

Note to devs:

Maybe it's an idea to add some 'SPOILER' tag? So with questions like these I could put the answer in SPOILER tags, so anyone who wants to think about it for him/herself before seeing the answer can chose so. (Ok Ok the real reason is that I won't look bad if I forget about this thread and someone continues on the question)

Oh challenge! :D

If the compiler has short circuit evaluation, the result should be...

ret TRUE
toot

if it does not have the kind of evaluation, then...

ret TRUE
ret FALSE
toot

But what if I change condition to if(returnTrue() || returnFalse() && returnTrue()), what would happen? ;) (Should open a new thread anyway...)

Edited 6 Years Ago by Taywin: n/a

Any decent compiler should have the short circuit evaluation (it still blows my mind why a compiler would do otherwise).

So if you think about your own change/question ... what do you think will happen?

@ OP If your compiler evaluates both functions in this code than I suggest you get a new one.

#include <iostream>
using std::cout;

bool returnTrue ( ) { cout << "ret TRUE\n"; return true; }
bool returnFalse( ) { cout << "ret FALSE\n"; return false; }

int main()
{
    if (returnFalse() && returnTrue())
        cout << "toot\n";
}

Edited 6 Years Ago by NathanOliver: n/a

hey, thanks everybody,

i m embarrassed to say this, but i cant reproduce the error. it seems that what for ex thelamb said (that the second condition is not evaluated if the first one is false) is true.

cheers,
richard

This question has already been answered. Start a new discussion instead.