views:

99

answers:

3

Hello, I'm using ptr_map for storing different types of pointers.

boost::ptr_map<string, any> someMap;

I store there some templated class objects:

someMap.insert("1", new SomeClass<int>());
someMap.insert("2", new SomeClass<float>());

Now I want to get values from map. Here is a sample with references:

template<typename T>
T &get(const string &someKey)
{
    try
    {
        return any_cast<EventType&>(mSignalAssociation.at(signalName));
    } catch(bad_any_cast &e)
    {
        // Logging here
    }
}

get< SomeClass<int> >("1"); // This works

But I don't like references, because I can't return, for example, NULL if the casting is bad or the object doesn't exist.

How can I get pointer from this map?

T *get(const string &someKey)
{
   return any_cast<EventType*>(mSignalAssociation.at(signalName));
}

This builds but fails at casting, why?

+1  A: 

how about this:

T *get(const string &someKey)
{
   return &any_cast<EventType&>(mSignalAssociation.at(signalName));
}

(Just a guess)

shoosh
This works, but why?
Ockonal
shoosh
+1  A: 

Function any_cast

If passed a pointer, it returns a similarly qualified pointer to the value content if successful, otherwise null is returned. If T is ValueType, it returns a copy of the held value, otherwise, if T is a reference to (possibly const qualified) ValueType, it returns a reference to the held value.

What you want are the pointer semantics. Also stop using ptr_map, it's a waste as has been pointed out in the comments.

map<string, any> someMap;
someMap["1"] = SomeClass<int>();
someMap["2"] = SomeClass<float>();

// this will be a valid pointer because someMap["1"] stores 
// an object of SomeClass<int>
SomeClass<int>* valid_ptr = any_cast<SomeClass<int> >(&someMap["1"]);

// this will be null pointer because someMap["2"] doesn't store
// an object of SomeClass<int>
SomeClass<int>* invalid_ptr = any_cast<SomeClass<int> >(&someMap["2"]);

If you need to store pointers for some reason to these SomeClass objects, then I think you'll have to do the memory management yourself (manually free the elements stored in any) and use an extra level of indirection to detect cast failures with a null pointer. Probably better to use something like boost::shared_ptr if you do.

map<string, any> someMap;
someMap["1"] = new SomeClass<int>();
someMap["2"] = new SomeClass<float>();

// this will be a valid pointer because someMap["1"] stores 
// an object of SomeClass<int>*
SomeClass<int>** valid_ptr = any_cast<SomeClass<int>*>(&someMap["1"]);

// this will be a null pointer because someMap["1"] does
// not store an object of SomeClass<int>*
SomeClass<int>** invalid_ptr = any_cast<SomeClass<int>*>(&someMap["2"]);
A: 

But I don't like references, because I can't return, for example, NULL if the casting is bad or the object doesn't exist

Ah... so that is the reason why you are doing these gymnastics with pointers, references, casting and memory managing containers! :)

As I pointed out previously; this will create unnecessary headaches. Fortunately, your problem has been solved - just look at Boost.Optional.

imran.fanaswala