Массив общих указателей на разные классы
Я пытаюсь выяснить, возможно ли создать массив общих указателей для разных типов.
Например, что-то вроде этого:
vector<shared_ptr<**???**>> v;
v.push_back(shared_ptr<int>(new int));
v.push_back(shared_ptr<MyClass>(new MyClass()));
или любым другим способом передать shared_ptr
, не зная его типа.
Ответы
Ответ 1
Более безопасный тип может быть:
/// header #include <boost/variant.hpp>
typedef boost::variant < boost::shared_ptr < T1 >, boost::shared_ptr < T2 >, ... > VariantT;
std::vector < VariantT > container;
container.push_back ( boost::shared_ptr < T1 > ( new T1 ) ); // or boost::make_shared
container.push_back ( boost::shared_ptr < T2 > ( new T2 ) ); // or boost::make_shared
Подробнее рассмотрите Boost.Variant library.
Ответ 2
Предполагая, что вы хотите хранить объекты, которые не наследуют общий класс, самым простым способом, который приходит на ум, является использование boost::any
.
Вы все же должны быть уверены в том, какой тип каждого объекта хранится в каждом индексе (т.е. иметь возможность выполнить правильное boost::any_cast
).
Вы должны сделать это, а не сохранить указатели на void
. Это ближе всего к семантически правильному способу хранения "того, что вы знаете, типа, но компилятор не делает", подразумевая приведение при извлечении значения.
В то время как оба указателя (any
и a void
) будут работать одинаково (указатель в сторону), если вы используете неверный тип, any
будет генерировать исключение bad_any_cast
(IIRC), в то время как указатель void
, вы получите поведение undefined. Простая попытка на coliru дала segfault.
Ответ 3
Так же, как любой основной тип указателя преобразуется в void*
, любой shared_ptr
преобразуется в shared_ptr<void>
:
vector<shared_ptr<void>> v;
v.push_back(make_shared<int>());
v.push_back(make_shared<MyClass>());
Теперь у вас есть vector
полностью разделенных стилями общих указателей. Однако вы ничего не можете сделать с этим интересным: вам нужно как-то узнать, какие типы хранятся в слотах vector
для их преобразования:
auto intptr = static_pointer_cast<int>(v[0]);
auto myclass_ptr = static_pointer_cast<MyClass>(v[1]);
Итак, хотя это можно сделать, это не очень полезно и, вероятно, указывает на сломанный дизайн.