Thread: Stl Set

  1. #1
    Registered User
    Join Date
    Sep 2002
    Posts
    24

    Stl Set

    I am trying to implement a set to store game objects and use the game attribute gameNum as a key to the set.

    I have overloaded the operator in the Game.cpp file as per below:

    Code:
    bool Game::operator<(Const Game& rhs)const
    {
        if(gameNum < rhs.gameNum)
       {    
           return true;
        }
        return false;
    }
    then in another class I have a STL set of games to which I insert
    all the games (inserting is working fine) .

    Code:
    set<Game*>schedule;
    set<Game*>::iterator si;
    once the set is filled with games and I try to retrieve one with find
    Code:
    si=schedule.find(gameToPlay);
    where gameToPlay is an int as is gameNum
    this gives me the error message:
    Invalid conversion from int to game - which I thought my overloaded operator made the key int??
    Is that correct and I am not calling it correctly
    or havent declared something correctly I am unsure.

    Any input appreciated
    Regards

  2. #2
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146

    Re: Stl Set

    Originally posted by nomes
    ...Any input appreciated
    Regards
    You said it, so I'm just going to make a tiny, insignificant suggestion because it's late and I'm tired.

    You could rewrite the following code:
    Code:
    bool Game::operator<(Const Game& rhs)const
    {
        if(gameNum < rhs.gameNum)
       {    
           return true;
        }
        return false;
    }
    to:
    Code:
    bool Game::operator<(Const Game& rhs)const
    {
         return gameNum < rhs.gameNum;
    }
    I think the latter looks more purdy
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  3. #3
    Amateur
    Join Date
    Sep 2003
    Posts
    228
    I don't see why your operator would have made the key int. Because the STL documentation I have says that find() recieves a parameter which is of type key_type which expands to be the first template parameter, i.e. your Game class.

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    161
    A std::map<int, Game*> might be more suitable for your situation.

  5. #5
    Registered User
    Join Date
    Sep 2002
    Posts
    24
    My understanding is that overloading the operator causes the comparison (and there for find) to compare between the specified attribute of the object gameNum attribute of the Game class. Otherwise how would STL compare two game objects ie which one is bigger smaller??

  6. #6
    Amateur
    Join Date
    Sep 2003
    Posts
    228
    Think about it a couple of seconds. Tell me, for starters, how could a function that takes a const Game & tells another to take an int parameter? How could just one function tell another which type its parameter has to be. It sounds really silly this way...
    Besides, STL uses typename/typedef to change its container types.

    Anyway, your problem is that a set<> cannot do what you are willing it to. Why not use a map<> with Game * as values and int as keys instead?

  7. #7
    Registered User
    Join Date
    May 2003
    Posts
    161
    My understanding is that overloading the operator causes the comparison (and there for find) to compare between the specified attribute of the object gameNum attribute of the Game class.
    The container has no idea about the implementation (and therefore, the gameNum member) of your class. It simply does a direct less-than comparison of the objects to determine where to place them in the set. In fact, since the keyval type of your set is a pointer, the operator< in your class won't be used at all - it will simply be ordered by the addresses of your objects.

    If you want to retrieve your pointers by gameNum, then you'll want to use an associative container. Like I stated above, a map container would probably be the best option.
    Code:
    map<int, Game*> schedule;
    
    schedule[10] = new Game;
    schedule[562] = new Game;
    
    Game* gameFiveSixTwo = schedule[562];
    If that's not what you want, then try to explain your problem in more detail and we can suggest a better solution.
    Last edited by thefroggy; 09-24-2003 at 11:54 PM.

  8. #8
    Registered User
    Join Date
    Sep 2002
    Posts
    24
    Yes I can understand why I SHOULD use a map - however I am trying to implement a set as can already use maps....

  9. #9
    Registered User jlou's Avatar
    Join Date
    Jul 2003
    Posts
    1,090
    I think you did everything right, almost.

    Your problem is that you have a set of Game pointers but your operator compares Game objects. If you make it a set of objects instead that should work fine.

    If for some reason you need or prefer a set of pointers here is one way I would do it:
    Code:
    #include <iostream>
    #include <set>
    
    struct Game
    {
        Game(int defaultGameNum) : gameNum(defaultGameNum) {}
        int gameNum;
    };
    
    struct GamePtrLessThan
    {
        bool operator()(const Game* const lhs, const Game* const rhs) const
        {
            // If rhs is null, then either both are null, or 
            // only rhs, either way return false.
            if (rhs == 0)
                return false;
    
            // Since rhs is not null but lhs is, return true.
            if (lhs == 0)
                return true;
    
            // Neither are null, so check the gameNum.
            return lhs->gameNum < rhs->gameNum;
        }
    };
    
    int main()
    {
        Game* pGame1 = new Game(1);
        Game* pGame2 = new Game(2);
        Game* pGame3 = new Game(3);
        Game* pGame4 = new Game(4);
        Game* pGame5 = 0;
    
        std::set<Game*, GamePtrLessThan> gameSet;
    
        gameSet.insert(pGame3);
        gameSet.insert(pGame1);
        gameSet.insert(pGame4);
        gameSet.insert(pGame5);
        gameSet.insert(pGame2);
    
        std::set<Game*, GamePtrLessThan>::const_iterator iterGamePtr = gameSet.begin();
        std::set<Game*, GamePtrLessThan>::const_iterator iterEnd = gameSet.end();
    
        for (; iterGamePtr != iterEnd; ++iterGamePtr)
        {
            Game* pCurrentGame = *iterGamePtr;
            if (pCurrentGame)
                std::cout << pCurrentGame->gameNum << std::endl;
            else
                std::cout << "Null pointer." << std::endl;
        }
    
        return 0;
    }
    EDIT: Emphasized important code.
    Last edited by jlou; 09-25-2003 at 04:27 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. optimising program
    By SONU in forum C Programming
    Replies: 1
    Last Post: 05-18-2008, 10:28 AM
  2. Set STL
    By DarkDot in forum C++ Programming
    Replies: 5
    Last Post: 05-02-2007, 02:58 PM
  3. STL Set erase()
    By R.Stiltskin in forum C++ Programming
    Replies: 11
    Last Post: 03-27-2007, 08:09 AM
  4. 6 measly errors
    By beene in forum Game Programming
    Replies: 11
    Last Post: 11-14-2006, 11:06 AM
  5. OpenGL Window
    By Morgul in forum Game Programming
    Replies: 1
    Last Post: 05-15-2005, 12:34 PM