tags:

views:

94

answers:

1

Hello, I'm packing some classes into ptr_map with any typed value.

class EventManager
{
   ptr_map<string, any> mSomeMap;
   public:
      typedef signals2::signal<void (int someSignature)> KeyEvent;
      EventManager()
      {
         mSomeMap["KeyPressed"] = new any(new KeyEvent());
      }
};

Now I want to restore my signal object from any. Here is a special function for this:

template<typename EventType>
EventType *get(const string &signalName)
{
    try {
        return any_cast<EventType*>(mSomeMap[signalName]);
    } catch(bad_any_cast &e){}
}

As you could remember, the boost's signals are noncopyable so I can store only pointers and my function should return pointers too.

Now sample usage:

evManager.get<EventManager::KeyEvent>("KeyPressed");

Here I get segfault. I checked the types of each objects in the get function:

typeid(EventType).name()
→ N5boost8signals26signalIFvRN2sf5Event8KeyEventEENS0_19optional_last_valueIvEEiSt4lessIiENS_8functionIS6_EENSB_IFvRKNS0_10connectionES5_EEENS0_5mutexEEE

mSignalAssociation[signalName].type().name()
→ N10__cxxabiv119__pointer_type_infoE

What's wrong is there? The segfault at line with casting. Any object should consist of inserted type or not? Why it doesn't want to cast.

+3  A: 
ptr_map<string, any> mSomeMap;

...
    mSomeMap["KeyPressed"] = new any(new KeyEvent());

Do you realize what happens here? First, you create a KeyEvent object dynamically which results in a pointer. Then this pointer is wrapped into an any-object which is also dynamically created which also returns a pointer which is then again wrapped in another any object implicitly by the assignment.

Also, for extracting the right value from an any object you need to know the exact type. So, for example, if you pack a Derived-pointer into an any object, you won't be able to access it via an any_cast<Base*> because Base* and Derived* are different types in terms of the std::type_info objects boost::any uses to keep track of types. boost::any just doesn't know how to convert the packed Derived-pointer to your Base-pointer.

Is there a special reason why you wrap so many things in any-objects including pointers to any-objects? Wouldn't it make sense to use something like a ptr_map<KeyType,BaseType>? You know that if you pack a pointer into an any object that you still need to delete the pointees yourself, right? The any-object is not going to do this for you.

sellibitze
I have to store different function signatures in the map. The boost signals are templated and noncopyable. So the only way of storing is pointer and 'any', right?
Ockonal
Did you get the first paragraph? mSomeMap["KeyPressed"] is an lvalue of boost::any type which you assign a pointer to. So this pointer to an any object is wrapped in another any-object. Surely you don't want to do this. The proper cast would be somehting like this: any_cast<EventType*>(*any_cast<any*>(mSomeMap["KeyPressed"]))
sellibitze
@sellibitze, You said "a pointer which is then again wrapped in another any object implicitly by the assignment". But isn't ptr_map holding boost::any*, and shouldn't this be a simple pointer assignment?
Nikola Smiljanić
@Nikola: No, ptr_map offers a "mixed" interface where operator[] returns an lvalue of the pointee which might be default constructed. either I'm wrong or the OP needs to read the documentation of boost::any and boost::ptr_map more closely. I actually don't see why ptr_map is needed here, a plain map<...,any> suffices.
sellibitze
@sellibitze: I've just realized what you're saying. The whole point of pointer containers is to hide pointers.
Nikola Smiljanić
Hm, I understand the problem. So I could make my any object as non pointer. It compiles in this way: `mMap["KeyPressed"] = any(new KeyEvent());` and casting: `any_cast<EventType*>(mMap[signalName]);` Is this right form?
Ockonal
@Ockonal: Yes, that would work. But the any(...) is not necessary and you also don't really need a ptr_map because you only store any-objects and nothing else. Keep in mind that if you store a pointer to a dynamically allocated object in an any-object, it doesn't free you from the burden of managing the life-time of the pointee. You should probably rethink your design.
sellibitze