Я работал над библиотекой упаковки для скриптовых языков (частично для изучения функций c ++ 11, а частично для конкретных нужд). Одна из возникших проблем заключается в экспорте унаследованных объектов на язык сценариев.
Проблема заключается в использовании прокси-объектов обернутых классов для вызова функций. В частности, если функция принимает Foo *
затем объектный прокси-сервер из любого используемого скриптового языка должен быть приведен соответствующим образом.
Есть два способа (о которых я могу подумать), чтобы соответствующим образом смоделировать прокси объекта:
template <class T>
struct ObjectProxy {
T *ptr;
};
или же:
struct WrappedClass {
virtual ~WrappedClass() {}
};
struct ObjectProxy {
WrappedClass *ptr;
template <typename T>
boost::shared_ptr<T> castAs() {
return boost::dynamic_pointer_cast<T>(instance);
}
};
Проблема с первой версией заключается в том, что вам нужно заранее знать, какой тип ObjectProxy
указывает на. К сожалению, нет простых решений для этого (см. Многие из моих предыдущих вопросов). После некоторого исследования похоже, что большинство популярных библиотек, которые делают это (например, boost :: python, LuaBind и т. Д.), Хранят график всех отношений классов, чтобы обеспечить правильное приведение.
Второй метод избегает необходимости делать все это, но добавляет ограничение, которое каждый переносимый класс должен наследовать от WrappedClass.
Вот мой вопрос: может ли кто-нибудь придумать какие-либо серьезные проблемы, помимо того, что он немного раздражает пользователя, со вторым подходом? Даже если вы не создали конкретный класс, вы всегда должны иметь возможность подкласса его. Например, если у вас есть какая-то библиотека, предоставьте класс Foo
тогда вы могли бы сделать:
class FooWrapped: public Foo, public WrappedClass {};
Это делает вещи немного менее плавными для пользователя (хотя я искал способы автоматизации этого), это означает, что вы можете полагаться на встроенный dynamic_cast, а не на то, чтобы писать свой собственный вариант.
редактировать
добавленной castAs()
сделать пример использования более понятным
Ваша проблема звучит как что повышение :: любой был разработан, чтобы решить. Решение в основном объединяет ваши две идеи: (код не проверен)
struct ObjectProxyBase {
virtual ~ObjectProxyBase() {}
};
template <class T>
struct ObjectProxy : public ObjectProxyBase {
T *ptr;
};
template <class T>
T *proxy_cast(ObjectProxyBase *obj) {
auto ptr = dynamic_cast<ObjectProxy<T> *>(obj);
if (!ptr)
return nullptr;
return ptr->ptr;
}
Других решений пока нет …