Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

std::map giving me an error I don't understand

Status
Not open for further replies.

Kalisto

Programmer
Feb 18, 2003
997
GB
I have never worked with maps before, but am playing around with them to solve a problem that we have at work. (I won't detail it again here, as I have mentioned it elsewhere !)

Basically I have a map defined as std::map<Foo,Bar> where foo is an enumerated type, and bar is a struct that coresponds to that type.

When I attempt to insert data into the map I get the error Cannot convert element 1 from foo to std::_tree<>::iterator

eg,

enum FOO {AB,CD};

struct validator_AB : public validator_base {....};

validator_AB myAB;
validator_CD myCD;

std::map<FOO,validator_base>;

myMap.insert(AB,validator_AB);
myMap.insert(CD,validator_CD);

OK, it has to be something easy, but what ? (apologies if this is in the book, but thats at home, and the technet CD's don't make the answer obvious to me, being as I am a bear of little brain.

Cheers,
K
 
It is usually bad practice (if possible at all) to store multiple types in the same container (even though they share the same base class).

You gotta realize that the map is a map of validator_base. When inserting etc it might use the validator_base's default constructor or copy constructor, it has no idea about any subclasses.

One workaround could be to store validator_base pointers in the map, but you'd have to &quot;manually&quot; call new and delete when appropriate (and dont forget the virtual destructor), and somehow ensure that the objects are valid for as long as the map holds them.

For more elaboration on the subject read Scott Meyers' &quot;More effective C++&quot; (Item 3: Never treat arrays polymorphically)


/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
OK, I take your point, but I have 27 different validator functions tied to user defined 'types', some with complex validation rules.
I am storing pointers, that was a typo when I tried to explain it, but that doesn't explain the error message on the enum.

Can you see a different way I can handle this, rather than using a map. (It needs to be extensible, and I'd rather just have a container mapping type -> validator, than a whole pile of if statments, cases etc.)
 
Not sure if the enum is the problem, but you could try with
std::map<int,validator_base*> TheMap;

Just to see if it works better (if not the problem is something else since int is definately a valid key).

std::map is usually nice, but since I'm not sure about what your app. is supposed to accomplish I cant say what other (if any) ways to handle it would be best. Perhaps take a look into the Visitor Pattern? *shrug*

/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
another thing:

if you use map (instead of if...else if...) I guess you'd initially have to construct all validators and put them in the map even if you would only use 1.

Is it a parser thingie? Then perhaps consider using different token types instead of enums. Each token type would have its own validation gizmo, and only those tokens that are createad are...well....created.


/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
In effect it will have to parse the file yes, It is a proprietary format that has 30 or so types. The data is composed of tags, each of which contains a command reference (a few hundred of these in all), and each command has an associated 'Type', and the data should conform to that types format.

(At the moment I am only working on a subset of the commands to try and create an analyser to look at a problem we are having.) I'll google for visitor pattern and token types, unless you have a good online reference handy :)

Thanks for all the help so far, but I suspect that there will be more questions if I am to look at tokens and creating a full blown parser !

K
 
Well, mainly for fun I've made a small SDI calculator that parses expressions like:
Code:
1+5
1+4*(5-sin(pi/2))
foo = 20
bar = foo * 50
Output:
Code:
6
17
foo=20
bar=1000

When parsing the input it creates various tokens AdditionOperator, Identifier, Value etc.

I could mail it to you if you're interested (given an email address that is).

/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
well you could send it to vacatnmattAThotmaildotcom, if you would.
It may well show me a new way forwards.
Cheers,

K
 
oops, theprecursor is vacantmatt, not vacatnmatt !
 
You've got mail (no, not that horrible movie)

/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
Hmm...

Code:
myMap.insert( AB, validator_AB );

I'm not near a reference right now, so feel free to ignore me if I'm wrong, but doesn't insert want an iterator as its first argument?

Try:

Code:
myMap[ AB ] = validator_AB.


Also, as long as you're storing pointers, you might want to check out shared_ptr from which will keep you from having to manually delete your validators.
 
>but doesn't insert want an iterator as its first argument?

Not necessarily.

But you're almost right ;-)

It should probably be
Code:
myMap.insert(TheMapType::value_type(AB, validator_AB));



/Per

if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
 
I got to a reference and I was right; that 2-argument version of insert was wanting to treat AB as a &quot;hint&quot; iterator. The other 2-argument version of map::insert takes 2 iterators and inserts all the stuff from that range. Neither of those fit.

So yeah, that's what caused your error, and both mine (using the indexing operator) and PerFnurt's (using the 1-argument insert) last examples should work, assuming you're still trying to use the map.
 
I usually use std::make_pair to insert into a map:

Code:
myMap.insert(std::make_pair(AB,pValidator_AB));
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top