I am attempting to understand how to use the MAP (caps for emphasis) standard template. I have figured out how to create a multimap, and how to add items to it, but I am having difficulty trying to reread the multimap. The map declaration looks like this:
// Using a string object for both the key
// and the item
typedef multimap<string, string> NameList;
typedef NameList::iterator NameIt;
NameList Names;
NameIt CurrentName;
// An example of adding one element
// to the map:
string NameA1 = "Patty Anderson";
string NameA2 = "Anderson";
Names.insert(NameList::value_type(NameA2, NameA1));
// This is the code I am trying to use to
// output the list to the console:
// Using a string object for both the key
// and the item
typedef multimap<string, string> NameList;
typedef NameList::iterator NameIt;
int main()
{
NameList Names;
NameIt CurrentName;
// An example of adding one element
// to the map:
string NameA1 = "Patty Anderson";
string NameA2 = "Anderson";
Names.insert
(NameList::value_type(NameA2, NameA1));
Thanks, Centaur. The while loop worked, but strangely enough, the for loop did not. Go figure.
proxima centaur
October 10th, 2002, 10:07 AM
No problem.
But it really mystifies me as to WHY the for loop sometimes works and sometimes doesn't.
Anybody can help us on that topic?
:)
willchop
October 10th, 2002, 10:19 AM
Why is there a semi-colon after the for loop in the OP's example?
Maybe the compiler sees the loop is a no-op and is optimizing the
loop out of the code completely. This would cause the iterator
to never get initialized.
regards, willchop
pedantic
October 10th, 2002, 10:25 AM
Geez...felled by the stupidest newbie mistake on the books. Yeah, that was the problem. Remove the semi colon and the For loop worked like a charm. Thanks everyone for your help.
proxima centaur
October 10th, 2002, 11:21 AM
Ah!!!!!!!!!!!!!!! thanks willchop !
I didn't see the friggin' semi-colon! That's why it works on my version of the for loop! :D
Don't worry pedantic, we were both as blind as mice! hehehe
Now I understand what happens. You parse the whole multimap and after the loop, your iterator points to Names.end() which is NOT the last element of the map, but rather a flag to tell the iterator when to stop. When you try to access the data pointed by Names.end(), it is an illegal operation punishable by crash.
Ok... I feel better now. I thought the compiler was misbehaving.
pedantic
October 10th, 2002, 11:27 AM
Though I'll add my thanks to willchop, I have to say that I don't feel particularly better about it...(grin).
RNEELY
October 11th, 2002, 11:46 AM
Please help STL Gurus. It seemed to me that one could overload the copy function template to copy multimap value seconds to an ostream iterator. But unfortunately, the following doesn't compile. I get the following error for the copy() call below:
c:\program files\microsoft visual studio\vc98\include\xutility(19) : error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::alloc
int main(int argc, char* argv[])
{
NameList Names;
NameIt CurrentName;
// An example of adding one element
// to the map:
string NameA1 = "Patty Anderson";
string NameA2 = "Anderson";
Names.insert
(NameList::value_type(NameA2, NameA1));
Well one potential error is that you may have two versions of "copy" going that are ambiguous. You have the std::copy, and your own template copy function. I would either
a) call it something else besides copy, or
b) put the scope resolution ::copy() when you call it, or
c) put your version of copy in a namespace and prepend your call to copy with the namespace.
This won't solve your current error, but it is an error that some compilers would have let you know about since the STL headers may include <algorithm> which will include std::copy.
The "second" is not a function call, so remove the parentheses.
Regards,
Paul McKenzie
RNEELY
December 3rd, 2002, 09:54 AM
Paul,
Thanks for your response. I cleaned up the code with the suggestions, but I still get the error described below.
I can't figure this one out. Does anyone have any ideas?
Regards,
-Ron
int main(int argc, char* argv[])
{
cout << "Welcome to MultiMap Fun!" << endl << flush;
NameMMap Names;
NameMMapIt CurrentName;
// An example of adding one element
// to the map:
string NameA1 = "Patty Anderson";
string NameA2 = "Anderson";
Names.insert(NameMMap::value_type(NameA2, NameA1));
ostream_iterator<string> out(cout, "\n");
cpy(Names.begin(), Names.end(), out); // <- error C2783 here
// error C2783: could not deduce template argument for '__formal'
// A template argument cannot be deduced by the compiler. For example:
// template<class T1, class T2> T1 f(T2){ }
// f(1);
cout << endl << flush;
cout << "Press any key to end..." << endl << flush;
_getch();
return 0;
}
</code>
PaulWendt
December 3rd, 2002, 11:31 AM
Try the following code changes to your cpy definition:
After examining some old points, though, I can't figure out why
you're not just using std::copy() [granted, I didn't peruse the
thread TOO intensely].
Edit: I think you just want to print out the map's values; I think
you could use for_each and a functor instead of using your own
version of copy. To each his own :)
--Paul
RNEELY
December 4th, 2002, 11:01 AM
Thanks Paul.
Yes, I am learning STL and I appreciate your help. I rewrote std::copy() as a learning exercise. for_each sounds cool.
It was "typename" that made the difference here:
I didn't know such a keyword existed. But I should have known the following which works as well:
template <class NameMMapIt, class OutputIterator>
A good understanding of templates seems predicate to understanding STL. I guess when you are defining a template class or function you must always use typename or class for template parameters. And that it is when you are instantiating, or the compiler automatically instantiates, the template the argument types are passed in to the template. I mixed both ways for my template arguments in my template definition.
Regards,
-Ron
PaulWendt
December 4th, 2002, 12:12 PM
Oh alright, I gotcha. I think when I was reading about copy, I
saw a "mock-up" implementation of it so that squelched my desire
to do my own; trust me, I like to know what's going on behind
the scenes too [just not when I don't have to].
--Paul
coldsnake
December 5th, 2002, 01:25 AM
original code:
for(CurrentName = Names.begin(); CurrentName != Names.end(); ++CurrentName);//care this, should not has a semicolon
{
cout << (*CurrentName).second << endl;
}
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.