|
-
October 10th, 2002, 08:30 AM
#1
Understanding the map template
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:
#include <map>
#include <string>
#include <iostream>
// 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:
for(CurrentName = Names.begin(); CurrentName != Names.end(); CurrentName++);
{
// Program crashes here.
cout << (*CurrentName).second << endl;
}
When I get to the cout line of code, the program blows up, even though I am practically copying the line from the VC++ example in their help files.
Can anyone tell me what they think I am doing wrong?
TIA.
-
October 10th, 2002, 09:02 AM
#2
I don't know what's wrong with your code it crashes when I run it here too, but this way of parsing the tree works:
Code:
CurrentName = Names.begin();
while( CurrentName != Names.end() )
{
cout << (*CurrentName).second;
cout << endl;
++CurrentName;
}
Mystifying.
Edit:
Actually, this also works. I don't know what is wrong with the original code, but here's my code that works:
Code:
#include <map>
#include <string>
#include <iostream>
using namespace std;
// 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));
CurrentName = Names.begin();
while( CurrentName != Names.end() )
{
cout << (*CurrentName).second;
cout << endl;
++CurrentName;
}
for( CurrentName = Names.begin(); CurrentName != Names.end(); CurrentName++ )
{
cout << (*CurrentName).second;
cout << endl;
}
}
Last edited by proxima centaur; October 10th, 2002 at 09:09 AM.
Martin Breton
3D vision software developer and system integrator.
-
October 10th, 2002, 09:40 AM
#3
Re: Using Maps
Thanks, Centaur. The while loop worked, but strangely enough, the for loop did not. Go figure.
-
October 10th, 2002, 10:07 AM
#4
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?
Martin Breton
3D vision software developer and system integrator.
-
October 10th, 2002, 10:19 AM
#5
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
Last edited by willchop; October 10th, 2002 at 10:22 AM.
-
October 10th, 2002, 10:25 AM
#6
Making MAP work
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.
-
October 10th, 2002, 11:21 AM
#7
Ah!!!!!!!!!!!!!!! thanks willchop !
I didn't see the friggin' semi-colon! That's why it works on my version of the for loop! 
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.
Martin Breton
3D vision software developer and system integrator.
-
October 10th, 2002, 11:27 AM
#8
End of all maps
Though I'll add my thanks to willchop, I have to say that I don't feel particularly better about it...(grin).
-
October 11th, 2002, 11:46 AM
#9
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
Is it possible to do what I am attempting?
Thanks in advance.
Regards,
-Ron
- //////////////////////////////////////////////////////////
// multimapfun.cpp
#include <iostream>
#include <string>
#include <map>
#include <iterator>
using namespace std;
typedef multimap<string, string> NameList;
typedef NameList::iterator NameIt;
template <NameIt, class OutputIterator>
OutputIterator copy(NameIt first, NameIt last, OutputIterator result)
{
while(first!=last)
{
*result++ = (*first++).second();
}
return result;
}
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));
ostream_iterator<string> out(cout, "\n");
copy(Names.begin(), Names.end(), out); // <- error here
cout << endl << flush;
return 0;
}
//
//////////////////////////////////////////////////////////
-
October 11th, 2002, 11:51 AM
#10
ooops. the whole error message is as follows
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
ator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' (or there is no acceptable conversion)
c:\working\utility\roncreations\cpp\stl\multimapfun\multimapfun.cpp(42) : see reference to function template instantiation 'class std::ostream_iterator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,c
har,struct std::char_traits<char> > __cdecl std::copy(class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::all
ocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::multimap<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char
,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,cl
*** std::allocator<char> > > >::_Kfn,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char
> > > >::iterator,class std::_Tree<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::bas
ic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,struct std::multimap<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::_Kfn
,struct std::less<class std::basic_string<char,struct st
::char_traits<char>,class std::allocator<char> > >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > >::iterator,class std::ostream_iterator<class std::basic_string<char,struct std::char_t
raits<char>,class std::allocator<char> >,char,struct std::char_traits<char> >)' being compiled
-
October 11th, 2002, 12:50 PM
#11
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.
Regards,
Paul McKenzie
-
October 11th, 2002, 01:00 PM
#12
Also, another error is here:
Code:
// *result++ = (*first++).second(); // Error!!
*result++ = (*first++).second; // Correct
The "second" is not a function call, so remove the parentheses.
Regards,
Paul McKenzie
-
December 3rd, 2002, 10:54 AM
#13
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
<code>
//////////////////////////////////////////////////////////
// multimapfun.cpp
#pragma warning( disable : 4786) // MSVC++ truncates debug information to '255'
#include <conio.h>
#include <iostream>
#include <string>
#include <map>
#include <iterator>
using namespace std;
typedef multimap<string, string> NameMMap;
typedef NameMMap::iterator NameMMapIt;
template <NameMMapIt, class OutputIterator>
void cpy(NameMMapIt first, NameMMapIt last, OutputIterator result)
{
while(first!=last)
{
*result++ = (*first++).second;
}
return result;
}
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>
-
December 3rd, 2002, 12:31 PM
#14
Try the following code changes to your cpy definition:
Code:
template <typename NameMMapIt, typename OutputIterator>
OutputIterator cpy(NameMMapIt first, NameMMapIt last, OutputIterator result)
{
while (first!=last)
{
*result++ = (*first++).second;
}
return result;
}
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
Last edited by PaulWendt; December 3rd, 2002 at 12:35 PM.
-
December 4th, 2002, 12:01 PM
#15
thanks
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:
template <typename NameMMapIt, typename OutputIterator>
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|