Здравствуйте, jazzer, Вы писали:
J>А почему бы в таком случае не использовать boost::function напрямую (или вообще boost::signal)? Он шаблонов не требует, у него тип нормальный, а в замыкание при конструировании что угодно можно засунуть, не нужно никаких дополнительных void*-параметров.
велосипедостроение потому что boost::signal напрямую использовать не получится — хочется фильтрацию и приоритеты вызовов. function кушает 16 байт и дает вызов по указателю на член + вызов виртуальной функции. Мои два указателя кушают 8 байт и дают простой вызов функции по указателю. Хотя конечно function значительно более удобен для оборачивания всяких лямбд. Может быть и перееду в конце концов на него.
Однако к первоначальному вопросу это отношения не имеет — хотелось определять тип источника сигнала и предпринимать некоторые действия в зависимости от этого.
Судя по этой теме, никакой волшебной пули нет — или надо в качестве источника иметь некий объект с доп информацией, или внешний реестр источников.
Здравствуйте, enji, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>А почему бы в таком случае не использовать boost::function напрямую (или вообще boost::signal)? Он шаблонов не требует, у него тип нормальный, а в замыкание при конструировании что угодно можно засунуть, не нужно никаких дополнительных void*-параметров.
E>велосипедостроение потому что boost::signal напрямую использовать не получится — хочется фильтрацию и приоритеты вызовов. function кушает 16 байт и дает вызов по указателю на член + вызов виртуальной функции. Мои два указателя кушают 8 байт и дают простой вызов функции по указателю. Хотя конечно function значительно более удобен для оборачивания всяких лямбд. Может быть и перееду в конце концов на него.
Если ты знаешь, какие типы могут быть, и при этом не хочешь наследовать все от одного базового типа, но знаешь все возможные базы — попробуй boost::variant с этим набором возможных базовых типов.
Здравствуйте, TarasB, Вы писали:
TB>Здравствуйте, jazzer, Вы писали:
J>>Нет, нельзя. dynamic_cast мог бы, но он не работает с void*, ему нужен указатель на объект реального класса.
TB>Ну так подсунь ему не void* а BasicRootClassOfAllClasses, все нужные классы наследуй от него.
у него там int в примере есть, как нафиг BasicRootClassOfAllClasses
Здравствуйте, TarasB, Вы писали:
TB>Здравствуйте, jazzer, Вы писали:
J>>у него там int в примере есть, как нафиг BasicRootClassOfAllClasses
TB>Пусть обернёт в класс тогда этот свой инт.
Здравствуйте, enji, Вы писали:
E>Хочется узнать, указывает ли void* на конкретный тип E>По идее можно проверить vptr, но к нему кроскомпиляторно не подберешься, да и всякие случаи вроде множественного наследования...
В общем случае, это невозможно, void* — это слишком хорошо стёртый тип. Особенно, с учётом того, что можно взять указатель на неполиморфную базу полиморфного наследника — она ничем не отличается от члена-данного, кроме тайного знания, что это не член, а база.
Если класс полиморфный, то обычная практика — поместить vfptr в самое начало лэяута. (Это не оговаривается стандартом, так же, как не оговаривается вообще механизм виртуальных функций и rtti; но MS- и linux-совместимые компиляторы делают именно так).
При этом неполиморфные базы смещаются, а если есть несколько полиморфных баз — то первая из них будет с нулевым смещением, а остальные со своими vfptr-ами — как придётся.
(Тут я хотел написать много слов про dynamic_cast, в том числе про dynamic_cast<void*>, но проще будет отослать к первоисточникам и толкованиям — стандарту и Страуструпу).
Разумеется, dynamic_cast применительно к неполиморфным объектам — это неопределённое поведение. Потому что, представьте себе, что там по нулевому смещению находится указатель на какую-нибудь мусорную таблицу виртуальных функций. Можно получить всё, что угодно, от защиты памяти до исполнения произвольного кода.
Отсюда мораль
— или сдерживать себя и ограничиться какой-нибудь строгой иерархией (не void*, а MyRootType*)
— или сделать внешнюю информацию о типе — хоть boost::any, хоть tagVARIANT рядом держать, — способов много
Здравствуйте, enji, Вы писали:
E>велосипедостроение потому что boost::signal напрямую использовать не получится — хочется фильтрацию и приоритеты вызовов. function кушает 16 байт и дает вызов по указателю на член + вызов виртуальной функции. Мои два указателя кушают 8 байт и дают простой вызов функции по указателю. Хотя конечно function значительно более удобен для оборачивания всяких лямбд. Может быть и перееду в конце концов на него.
Если источники сигнала всегда приходят типизированными, и только внутри твоей библиотеки заворачиваются в void*, то можно всегда брать их внутрь шаблонным методом/конструктором и класть рядом с void* указатель на шаблонную реализацию интерфейса, через котрый можно всё разрулить...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском