Thread: problem with a map iterator

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    22

    problem with a map iterator

    Hi,
    I have a map of an object of a certain class and a vector of another class. I have an iterator for this map which I need to 'jump' several positions forward. Here is the relevant code:
    Code:
    std::map<Lit, std::vector<Index> >::iterator mapfill;
    mapfill = indices.begin();  //reset the iterator
    std::map<Lit, std::vector<Index> >::size_type st;
    st+=(name*2-2);
    mapfill+=st;
    the last line doesn't compile. At first I tried simply this:
    Code:
    mapfill+=(name*2-2);
    but this didn't compile either. I find this really strange, since ++mapfill works perfectly, and as far as i know ++ is the same as +=1.
    Any ideas on this would be much appreciated.

    Oh yes, forgot to say i'm compiling this on gcc.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    What is 'name'?

    Usually you can jump an iterator several positions using the advance function, i.e.

    Code:
    #include <algorithm>
    
    ...
    
    mapfill = indices.begin();
    
    ...
    
    std::advance(mapfill,3);  // Advances mapfill iterator to the 4th element, 3rd from beginning
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    22
    hk_mp5kpdw (hope i got this right ) thanks a lot, that solves my problem.
    'name' is an int, so should work fine.
    Once again, thank you.

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    I find this really strange, since ++mapfill works perfectly, and as far as i know ++ is the same as +=1.
    Iterators aren't integers. Integers have a whole range of operators defined: +, -, /, *, %, etc. Integers also have "op=" versions of those operators: +=, *=, %=, etc. Integers also have the ++ and -- operators defined for them.

    On the other hand, iterators don't necessarily define all those operators. Iterators are designed for traversing a range of values, so iterators define the operator++ and operator-- for stepping through a range of objects, and they define the operator* so you can dereference the iterator and get the object the iterator points to, and they define the operator!= to test for the end of the range.

    Iterators also provide random access to a range by defining the operator+ and the operator-, and they define operator= as well, so you should be able to do some "pointer arithmetic" with an iterator like this:

    mapfill + st

    That allows you to move to any position in the range. And, you can do this:

    mapfill = mapfill + st;

    I think maybe operations like that probably aren't used too much, so the "op=" versions of the operators aren't defined for iterators. Instead, it's probably more common to use the expression mapfill + st instead.

    [edit]The op= version of operator+ works in this code:
    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Index
    {
    public:
    	int i;
    	Index(int in)
    	{
    		i = in;
    	}
    	void show()
    	{
    		cout<<"Index object: "<<i<<endl;
    	}
    };
    
    int main()
    {
    	Index a(0), b(1), c(2), d(3), e(4);
    	Index arrI[] = {a, b, c, d, e};
    	
    	arrI[2].show();
    
    	vector<Index> vec(arrI, arrI + 5);
    	vector<Index>::iterator vecfill;
    
    	vecfill = vec.begin();
    	vecfill->show();
    	
            vecfill += 3;
    	vecfill->show();
    
            return 0;
    }
    Maybe you should try your code with integer literals and see if it works.
    [/edit]


    I have a question: how did you get the following declaration to work:

    std::map<Lit, std::vector<Index> >::iterator mapfill;

    If I define a class called Lit and another class called Index, my compiler gives me a bunch of errors when I do this:
    Code:
    using namespace std;
    
    map<Lit, vector<Index>> M;
    
    map<Lit, vector<Index>>::iterator mapfill;
    The compiler doesn't understand that notation, and complains about a bunch of syntax errors. What am I doing wrong?
    Last edited by 7stud; 04-29-2005 at 12:57 PM.

  5. #5
    Registered User
    Join Date
    Sep 2004
    Posts
    719
    7stud:

    notice the space between the 2 >'s

    map<Lit, vector<Index> >::iterator mapfill;

    ..........remember, >> is an operator

    edit: yea, it's kind of stupid. i imagine they went and wrote all the code for the STL and in the middle of typing a declaration they stopped and said, "oh crap!"
    Last edited by misplaced; 04-29-2005 at 05:34 AM.
    i seem to have GCC 3.3.4
    But how do i start it?
    I dont have a menu for it or anything.

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Quote Originally Posted by misplaced
    ..........remember, >> is an operator
    Now, I do. Thanks.

    Another question: whenever I use vectors in VC++6, I get a bunch of warnings, which are all similar to this:

    identifier was truncated to '255' characters in the debug information

    Is there a way to supress all that? Here is a small sample of what I get:
    c:\program files\c++microsoft visual studio\vc98\include\xtree(118) : warning C4786: 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator<In dex> >,std::less<Lit>,std::allocato
    r<std::vector<Index,std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >' : identifier was truncated to '255' characters in the debug information
    c:\program files\c++microsoft visual studio\vc98\include\map(46) : see reference to class template instantiation 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator< I
    ndex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >' being compiled
    c:\beginning c++\test2\main.cpp(37) : see reference to class template instantiation 'std::map<Lit,std::vector<Index,std::allocator<Ind ex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >' being compiled
    c:\program files\c++microsoft visual studio\vc98\include\xtree(118) : warning C4786: 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator<In dex> >,std::less<Lit>,std::allocato
    r<std::vector<Index,std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >::const_iterator' : identifier was truncated to '255' characters in the debug information
    c:\program files\c++microsoft visual studio\vc98\include\map(46) : see reference to class template instantiation 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator< I
    ndex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >' being compiled
    c:\beginning c++\test2\main.cpp(37) : see reference to class template instantiation 'std::map<Lit,std::vector<Index,std::allocator<Ind ex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >' being compiled
    c:\program files\c++microsoft visual studio\vc98\include\xtree(118) : warning C4786: 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator<In dex> >,std::less<Lit>,std::allocato
    r<std::vector<Index,std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >::iterator' : identifier was truncated to '255' characters in the debug information
    c:\program files\c++microsoft visual studio\vc98\include\map(46) : see reference to class template instantiation 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator< I
    ndex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >' being compiled
    c:\beginning c++\test2\main.cpp(37) : see reference to class template instantiation 'std::map<Lit,std::vector<Index,std::allocator<Ind ex> >,std::less<Lit>,std::allocator<std::vector<Index, std::allocator<Index> > > >' being compiled
    c:\program files\c++microsoft visual studio\vc98\include\xtree(118) : warning C4786: 'std::_Tree<Lit,std:air<Lit const ,std::vector<Index,std::allocator<Index> > >,std::map<Lit,std::vector<Index,std::allocator<In dex> >,std::less<Lit>,std::allocato
    r<std::vector<Index,std::allocator<Index> > > >::_Kfn,std::less<Lit>,std::allocator<std::vector< Index,std::allocator<Index> > > >::_Node' : identifier was truncated to '255' characters in the debug information
    c:\program files\c++microsoft visual studio\vc98\include\map(46) : see reference to class template

  7. #7
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  8. #8
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    lol. I was looking through some old posts yesterday, and I saw your nic, and today--here you are. That avatar always cracks me up.
    Last edited by 7stud; 04-29-2005 at 05:54 AM.

  9. #9
    Registered User
    Join Date
    Sep 2004
    Posts
    719
    Visual Studio 6 maintained at 255-character limit on identifiers in its
    debug information.

    #pragma warning( push, disable )
    i seem to have GCC 3.3.4
    But how do i start it?
    I dont have a menu for it or anything.

  10. #10
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    #pragma warning( push, disable )

    I put that at the top of my file, but I still get 70 warnings.

  11. #11
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    1)Is there a way to fill a map in the constructor if you have the keys in one array and the values in another array?

    2) How should you code your data to make it as easy as possible to fill a map?

  12. #12
    Registered User
    Join Date
    Sep 2004
    Posts
    719
    doh!

    dunno what i was thinking

    you need

    #pragma warning( disable : 4786 )
    i seem to have GCC 3.3.4
    But how do i start it?
    I dont have a menu for it or anything.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    First, += works on vector iterators because they are random access iterators. The map iterators are bidirectional iterators which is why they only allow ++ and --.

    >> 1)Is there a way to fill a map in the constructor if you have the keys in one array and the values in another array?

    You can do it, but it is probably not any better than inserting the values into the map. AFAIK you have to have a container of key, value pairs to use the map constructor, like this:
    Code:
    #include <iostream>
    #include <map>
    #include <list>
    #include <string>
    int main()
    {
    	int keys[] = { 1, 2, 5, 6, 3, 4 };
    	std::string values[] = { "one", "two", "five", "six", "three", "four" };
     
    	std::list<std::pair<int, std::string> > pairList;
    	for (int i = 0; i < 6; ++i)
    	{
    		pairList.push_back(std::make_pair(keys[i], values[i]));
    	}
     
    	std::map<int, std::string> dataMap(pairList.begin(), pairList.end());
     
    	std::map<int, std::string>::const_iterator iterPair = dataMap.begin();
    	std::map<int, std::string>::const_iterator iterEnd = dataMap.end();
    	for (; iterPair != iterEnd; ++iterPair)
    	{
    		std::cout << iterPair->first << " - " << iterPair->second << std::endl;
    	}
    }
    But you should just go ahead and insert the values directly into the map instead.

    >> 2) How should you code your data to make it as easy as possible to fill a map?

    It depends. If you generally insert all your data into the map at the same time, and then only access it to read the data, you might consider using a vector, pushing back all elements, and then using sort() to sort them. You can use algorithms like find() and binary_search() in place of the regular map functions. Doing one sort at the end is better than using insert in a map which sorts each element as it is inserted.

    If you don't insert all your data at the same time, then just inserting the data into the map as necessary should be fine. As long as you have a less than function available for your key there isn't much to worry about to make it easy to fill the map.

  14. #14
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Thanks for the tips Daved. I'm trying to make a map as the op presented. I'm still struggling a bit with how to organize the raw data to make it easiest to read into vectors and maps. Anyway, I can't get the map look up to work. I'm trying to access the values by using the keys, and I'm getting these errors:

    error C2679: binary '[' : no operator defined which takes a right-hand operand of type 'const struct std::pair<class Lit const ,class std::vector<class Index,class std::allocator<class Index> > >' (or there is
    no acceptable conversion)

    error C2228: left of '.show' must have class/struct/union type
    Error executing cl.exe.

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <map>
    
    #pragma warning( disable : 4786 )
    
    using namespace std;
    
    
    //The class Lit doesn't do anything except display() its int member:
    class Lit
    {
    public:
    	int i;
    	
    	Lit(int in)
    	{
    		i = in;
    	}
    	
    	void display()
    	{
    		cout<<"Lit object: "<<i<<endl;
    	}
    
    	bool operator<(const Lit& rhs) const  //MUST BE CONSTANT
    	{
    		return i < rhs.i;
    	}
    };
    
    //This class also doesn't do anything except show() its int member
    class Index
    {
    public:
    	int i;
    	Index(int in)
    	{
    		i = in;
    	}
    	void show()
    	{
    		cout<<"Index object: "<<i<<endl;
    	}
    };
    
    
    int main()
    {
    	//create some Index objects:
    	Index a(0), b(1), c(2), d(10), e(20), f(30), g(100), h(200), i(300);
    	Index arrI[] = {a, b, c, d, e, f, g, h, i};
    	
    	//create some Lit objects:
    	Lit u(10),v(20),w(30);  
    	Lit arrL[] = {u, v, w};   
    
    	
    	//create some Index vectors and fill them with the Index objects:
    	vector<Index> Ivec0(arrI, arrI + 3);
    	vector<Index> Ivec1(arrI + 3, arrI + 6);
    	vector<Index> Ivec2(arrI + 6, arrI + 9);
    
    	//create an array of the Index vectors:
    	vector<Index> ArrayOfVecs[] = {Ivec0, Ivec1, Ivec2};
    	
    
    
    /*	
    
        //test the data to see if everything is okey dokey:
    
    	vector<Index>::iterator vecfill;
    
    	vecfill = ArrayOfVecs[0].begin();
    	vecfill->show();
    	vecfill += 2;
    	vecfill->show();
    
    	vecfill = Ivec1.begin();
    	vecfill->show();
    	vecfill += 2;
    	vecfill->show();
    
    	vecfill = ArrayOfVecs[2].end();
    	(vecfill - 1)->show();
    	vecfill = Ivec2.begin();
    	vecfill->show();
    
    	if(arrL[0]<arrL[1])
    		cout<<"true"<<endl;
    	else cout<<"false"<<endl;
    */
    	
    	//declare the map and fill it with pairs:
            map<Lit, vector<Index> > M;
    	
            for(int ii = 0; ii < 3; ii++)
    	{
    		M.insert(pair<Lit,vector<Index> >(arrL[ii], ArrayOfVecs[ii]));
    	}
    	
    	
    	//create a map interator and attempt to access the 'values' using a 'key':
    	map<Lit, vector<Index> >::const_iterator mapfill;
    
    	for(mapfill = M.begin(); mapfill != M.end(); mapfill++)
    	{
    		M[*mapfill][0].show();
    	}
    
    	
    	//map<Lit, vector<Index> >::size_type st;
    
        return 0;
    }
    Last edited by 7stud; 04-29-2005 at 12:52 PM.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> M[*mapfill][0].show();

    If you are using iterators, then you don't need the operator[]:

    mapfill->first: The Lit object (key)
    mapfill->second: The vector<Index> (value)

    To access the data using the iterator (in this case the key is not used):
    Code:
    (mapfill->second)[0].show();
    To access the data using the key outside of the iterator loop (referencing variable v from above code):
    Code:
    M[v][0].show();

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to assign a map iterator to an int variable?
    By Masterx in forum C++ Programming
    Replies: 22
    Last Post: 05-02-2009, 09:05 AM
  2. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  3. Problem with static STL i.e. map
    By vijay_choudhari in forum C++ Programming
    Replies: 2
    Last Post: 10-26-2007, 05:56 AM
  4. Picture download problem
    By wingri in forum C Programming
    Replies: 10
    Last Post: 07-31-2007, 05:32 AM
  5. iterator copy problem
    By cdonlan in forum C++ Programming
    Replies: 2
    Last Post: 04-16-2005, 02:38 PM