0

I need helping trying to retrieve data held in a std::list<boost::shared_ptr<boost::any>>

I working on a Singleton Controller class with a private std::list. Client class(es) will be able to add/remove/edit concrete class objects to be used by the program through this Controller class.

The reason for using boost::shared_ptr is because I assign a unique objID to each concrete class created. Once instance objs are added to controller, user will be able to search and remove objs later. The Add(....) and Remove(...) overloaded methods for each concrete class work fine.

I am now trying to create getObject(int index) & setObject(int index) methods but can't seem to figure out how to cast the returned pointer to a Concrete class.

Please advise.

My current code:

//===============================================================
//Singleton.h controller class
private:    
static Singleton *mgr;

typedef boost::shared_ptr<boost::any> Shapes_Ptr;
//private static list
static std::list<Shapes_Ptr> shapes; 

public:
const Shapes_Ptr getObject( int index) const;  //Return Shape
Shapes_Ptr EditObject( const int index );      //Edit Shape

Info();  //Prints contents of instance to console screen

//===============================================================
//Singleton.cpp 

//Return Shape
const Shapes_Ptr getObject( int index) const
{
    int cc = 0;

    if ( (int)shapes.size() > ZERO && index < (int)shapes.size() )
    {
        list<Shapes_Ptr>::const_iterator i;

        for ( i = shapes.begin(); i != shapes.end(); ++i )
        {
            if ( cc == index )
            {
                return (*i);
                break;
            } 
            else { ++cc; }
        }//for-loop 
    }   
}

//Edit Shape
Shapes_Ptr EditObject( const int index )
{
    //same code as getObject()...
}


//===============================================================
//main.cpp 

Singleton *contrl= Singleton::Instance();

int main()
{
    for ( int i=0; i< 2; ++i )
    {
        contrl->CreateObject(Box2D() );
    }

    for ( int i = contrl->Begin(); i< contrl->End(); ++i )
    {
        if ( boost::any_cast<boost::any> (contrl->getObject(i)).type() == typeid(Physics::Box2D) )
        {
            //Code compiles but crashes on launch....
            any_cast<Box2D> (contrl->getObject(i) ).Info(); // <== ERROR CODE
        }
        //More if checks for other Concrete classes....
    }
}
badboy11
  • 541
  • 1
  • 6
  • 19
  • Can you explain what you are trying to accomplish? Have you tried running your existing code in a debugger? – John Zwinck Feb 09 '12 at 22:18
  • @John - Yes, I have ran the project in debug mode. I am getting a exception error `bad_cast` I am trying to create a getter/setter for the private `std::list` so I can iterate and print out the data as well as be able to called the setters for each data members in each element in the list. If there is a clean or better way of exposing elements of the list, please advise. – badboy11 Feb 09 '12 at 22:45
  • So what is this code supposed to be good for? Why do you want a singleton that doesn't know what types it contains, but contains them anyway? – John Zwinck Feb 09 '12 at 22:50
  • @John - I am trying to implement a Model-View-Controller. The Singleton is the Controller, one gateway to manage how many instances of all objects are created, plus it also assigns unique IDs so clients can search for. – badboy11 Feb 09 '12 at 23:01
  • Can you provide an example that will compile? I have a feeling it's a problem with your actual `any_cast(control->getObject(i))`. `getObject` returns a `Shapes_Ptr` _not_ a `Box2D`. It may be as simple as changing to `any_cast(control->getObject(i).get())`, but I cannot test that hypothesis without an example that will compile. That said, I'd look into John's answer below if I were you. – Chad Feb 10 '12 at 21:13

1 Answers1

0

Putting aside whatever the particular issue with your current code is, I think there is an issue with your design.

You have this Singleton manager class that acts as a sort of pool and also as you say assigns unique IDs to each object so they can be found later. But you know what lets code find objects? Pointers! If you use a normal pool, one per type hierarchy (so no more Boost Any), you may find it just as useful, and there will be less nasty if/else typeid-checking code (which everyone would agree is not a good use of RTTI, aside from being poor OOP).

So, what do you say? Chuck this, and use Boost Pool if you want something to allocate your objects from a central place, and use pointers as your unique IDs, thus avoiding lookups along the way.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436