woodings
woodings

Reputation: 7693

How can I check if the key exists in a std::map and get the map::iterator in if condition?

I'd like to define the variable in condition expression so that the variable scope would be within the if clause. This works fine,

if (int* x = new int(123)) { }

When I was trying to do a similar thing with map::iterator,

if ((map<string, Property>::iterator it = props.find(PROP_NAME)) != props.end()) { it->do_something(); }

I got error: expected primary-expression before ‘it’

What makes the difference between int* and map::iterator?

Upvotes: 1

Views: 442

Answers (3)

AnT stands with Russia
AnT stands with Russia

Reputation: 320777

There's no difference between int * and map::iterator in that regard. There's a difference in the surrounding semantic constructs that you are using with int * and map::iterator, which is why one compiles and other doesn't.

With if you have a choice of either

if (declaration)

or

if (expression)

Declaration is not an expression. You can't use a declaration as a subexpression in a larger expression. You cannot use a declaration as a part of explicit comparison, which is exactly what you attempt to do.

For example, if you attempted to do the same thing with int *, like this

if ((int* x = new int(123)) != NULL)

the code would not not compile for exactly the same reasons your map::iterator code does not compile.

You have to use

if (int* x = new int(123))

or

int* x = new int(123);
if (x != NULL)

or

int* x;
if ((x = new int(123)) != NULL)

As you can see above, int * exhibits exactly the same behavior as map::iterator.

In your example, it is impossible to declare it and perform its comparison with props.end() in ifs condition. You will have to use one of the above variants instead, i.e. either

map<string, Property>::iterator it = props.find(PROP_NAME);
if (it != props.end())

or

map<string, Property>::iterator it;
if ((it = props.find(PROP_NAME)) != props.end())

Choose whichever you like more.

P.S. Of course, formally you can also write

if (map<string, Property>::iterator it = props.find(PROP_NAME))

but it does not do what you want it to do (does not compare the iterator value to props.end()) and might not compile at all, since the iterator type is probably not convertible to bool.

Upvotes: 5

Branko Dimitrijevic
Branko Dimitrijevic

Reputation: 52157

Here is one way to limit it to a scope:

{
    auto it = props.find(PROP_NAME);
    if (it != props.end()) {
       it->do_something();
    }
}

Granted, this scope is not technically the "if scope", but should serve just as well for all practical intents and purposes.

As AndreyT already explained (+1), declaration can't transcend ( and ), which you did not use for int but you did for the iterator.

Upvotes: 1

Joe Runde
Joe Runde

Reputation: 253

Map iterators contain first and second, which point to the key and value, respectively. To access a member of the value, use it->second.do_Something()

Upvotes: 0

Related Questions