0

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?

manlio
  • 18,345
  • 14
  • 76
  • 126
Max Frai
  • 61,946
  • 78
  • 197
  • 306
  • Why are you using a `ptr_map`? `any` has value semantics, so it can be stored in a plain `map`. – Mike Seymour Jun 28 '10 at 12:57
  • That's exactly what I was thinking about. The `ptr_map` store a pointer to its argument so we have a pointer to a small structure which itself as a pointer to the real object. Talk about premature pessimization. – Matthieu M. Jun 28 '10 at 13:02

3 Answers3

1

how about this:

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

(Just a guess)

shoosh
  • 76,898
  • 55
  • 205
  • 325
  • Taking the address (& operator) of a reference variable gives you the address of the object the reference variable references. – shoosh Jun 28 '10 at 15:21
1

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"]);
Community
  • 1
  • 1
stinky472
  • 6,737
  • 28
  • 27
0

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.

Community
  • 1
  • 1
Imran.Fanaswala
  • 755
  • 4
  • 6