Вот что я пытаюсь сделать:
Я разрабатываю кроссплатформенную IDE (Linux и Windows), которая поддерживает плагины . Мне нужно поддерживать расширяемость с помощью инфраструктуры адаптера, аналогичной той, что предоставляет Eclipse. См. здесь для получения более подробной информации, но в основном мне нужно следующее:
Пусть Адаптированный
и Адаптированный
будут совершенно несвязанными классами, которые уже существуют, и которыми мы не являемся. разрешено изменять любым способом.Я хочу создать класс AdapterManager
, который имеет метод
template Adapted* adapt( Adaptee* object);
, который создаст экземпляр Adapted
с учетом экземпляра Adaptee
. Как именно создается экземпляр, зависит от функции адаптера, которую необходимо зарегистрировать в AdapterManager
. Каждый новый плагин должен иметь возможность добавлять функции адаптера для произвольных типов.
Вот мои мысли о возможном решении и почему оно не работает:
Функции RTTI C ++ 11 и класс type_info
предоставляют метод hash_code ()
, который возвращает уникальное целое число для каждого типа в программе. См. здесь . Таким образом, AdapterManager
может просто содержать карту, которая с заданными хэш-кодами для классов Adaptee и Adapter возвращает указатель функции на функцию адаптера. Это делает реализацию вышеупомянутой функции adjust ()
тривиальной:
template Adapted * AdapterManager :: adap (Adaptee * object)
{
AdapterMapKey mk (typeid (адаптировано) .hash_code (), typeid (Adaptee) .hash_code ());
Функция адаптера af = adapterMap.get (mk);
если (! af) вернуть nullptr;
return (адаптировано *) af (объект);
}
Любой плагин может легко расширить структуру, просто вставив дополнительную функцию в карту. Также обратите внимание, что любой подключаемый модуль может попытаться адаптировать любой класс к любому другому классу и добиться успеха, если существует соответствующая функция адаптера, зарегистрированная в AdapterManager
, независимо от того, кто ее зарегистрировал.
type_info
и потенциально различным результатам hash_code ()
, что приведет к сломать механизм выше. Функции адаптера, зарегистрированные из одного плагина, могут не всегда работать в другом плагине. Вопросы:
Обновление 1:
Этот проект использует структуру Qt для многих вещей, включая инфраструктуру подключаемых модулей. Qt действительно помогает в кроссплатформенной разработке. Если вам известно конкретное решение проблемы Qt, это тоже приветствуется.
Обновление 2:
н.м.Этот комментарий заставил меня понять, что я знаю о проблеме только теоретически и на самом деле не проверял ее. Поэтому я провел некоторое тестирование как в Windows, так и в Linux, используя следующее определение:
template
class TypeIdTest {
public:
virtual ~TypeIdTest() {};
static int data;
};
template int TypeIdTest::data;
Этот класс создается в двух разных разделяемых библиотеках / DLL с T = int. Обе библиотеки явно загружаются во время выполнения. Вот что я обнаружил:
В Linux все просто работает:
typeid
, находился по тому же адресу. В Windows два экземпляра «несколько» различны:
typeid
для разных экземпляров возвращает type_info
объектов по разным адресам. Однако эти объекты равны при тестировании с ==
. Соответствующие хэш-коды также равны. Похоже, что в Windows равенство между типами устанавливается с помощью имени типа - что имеет смысл. Все идет нормально. dynamic_cast
для преобразования экземпляра TypeIdTest
в производный тип через границы разделяемой библиотеки.
. Это может вызвать множество проблем и в основном запрещает использование статических полей в классах шаблонов. В целом, кажется, что даже в Windows все не так плохо, как я думал, но я все еще не хочу использовать этот подход, учитывая, что при создании экземпляров шаблонов все еще используются отдельные vtables и статическое хранилище. Кто-нибудь знает, как избежать этой проблемы? Я не нашел решения.