2010-06-19 2 views
0

Я собираю некоторые классы в ptr_map с любым типизированным значением.Кастинг от любого

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

Теперь я хочу восстановить свой сигнальный объект из любого. Здесь имеется специальная функция для этого:

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

Как вы могли бы вспомнить, сигналы подпиточного являются noncopyable, так что я могу хранить только указатели и моя функция должна возвращать указатели тоже.

Теперь пример использования:

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

Здесь я получаю Segfault. Я проверил типы каждого объекта в получить функции:

typeid(EventType).name() 
→ N5boost8signals26signalIFvRN2sf5Event8KeyEventEENS0_19optional_last_valueIvEEiSt4lessIiENS_8functionIS6_EENSB_IFvRKNS0_10connectionES5_EEENS0_5mutexEEE 

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

Что случилось там? Сегфект на линии с литьем. Любой объект должен состоять из вставленного типа или нет? Почему он не хочет бросать.

+2

Это может не вызвать проблемы, хотя это может замаскировать его, но ловить и игнорировать плохой бросок, а не возвращать значение, выглядит очень неправильно. – Stephen

+0

@stephen Я просто отрезал часть регистрации и другие вещи. Это не имеет значения в этой теме. – Ockonal

ответ

3
ptr_map<string, any> mSomeMap; 

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

Вы понимаете, что здесь происходит? Во-первых, вы создаете объект KeyEvent динамически, что приводит к указателю . Затем этот указатель обернут в любой объект, который также динамически создается, и он также возвращает указатель, который затем снова неинтересно переносится в другой любой объект путем назначения.

Кроме того, для извлечения правильного значения из любого объекта вам необходимо знать точный тип. Например, если вы упаковываете Derived -поинтер в какой-либо объект, вы не сможете получить к нему доступ через any_cast<Base*>, потому что Base* и Derived* - это разные типы в терминах std::type_info объектов. boost::any использует для отслеживания типов. boost::any просто не знает, как конвертировать упакованный Derived -поинтер в ваш Base -поинтер.

Есть ли особая причина, почему вы так много обертываете в any -объектах, включая указатели на any -объекты? Не имеет смысла использовать что-то вроде ptr_map<KeyType,BaseType>? Вы знаете, что если вы упаковываете указатель на какой-либо объект, который вам по-прежнему нужен, чтобы удалить указателей самостоятельно, не так ли? Любой объект не собирается делать это за вас.

+0

Мне нужно хранить различные сигнатуры функций на карте. Сигналы ускорения шаблоны и не подлежат копированию. Таким образом, единственным способом хранения является указатель и «любой», верно? – Ockonal

+0

Вы получили первый абзац? mSomeMap ["KeyPressed"] - это lvalue boost :: любого типа, которому вы назначаете указатель. Таким образом, этот указатель на любой объект завернут в другой объект. Конечно, вы не хотите этого делать. Правильный листинг будет выглядеть следующим образом: any_cast (* any_cast (mSomeMap ["KeyPressed"])) – sellibitze

+0

@sellibitze, Вы сказали «указатель, который затем снова будет завернут в другой любой объект неявным назначением». Но не ptr_map поддерживает boost :: any *, и не должно ли это быть простым назначением указателя? –

Смежные вопросы