Для контекста, я работаю над встроенной средой высокой надежности. Некоторые из ограничений, налагаемых в этой среде, включают;
- Нет динамического c выделение памяти
- Требуется соответствие c ++ 14 или ниже
- Нет информации о типе времени выполнения
Таким образом, конечный результат заключается в том, что я хочу класс, содержащий const std::array
указателей типа BaseInterface, который может содержать выделенный стек набор произвольных производных классов.
Рассмотрим неполный пример ниже.
Примечание: Конструктор BaseHandler и комментарии к переменным-членам для более контекстных вопросов.
#include <array>
#include <tuple>
class BaseInterface {
public:
virtual void DoSomething() = 0;
};
class Derived1 : public BaseInterface {
void DoSomething() override {}
};
class Derived2 : public BaseInterface {
void DoSomething() override {}
};
/**
* @brief Handles stack allocated polymorphic arrays
*
* @tparam base_ptr_t pointer type that each element must derive from
* @tparam derived_t parameter pack of derived variables
*/
template <class base_ptr_t, class... derived_t>
class BaseHandler {
public:
BaseHandler(Elements &&... element)
: memory_store_x_{std::forward<derived_t>(element)...},
array_(/* How to make each elementwise pointer point to each element in the tuple/array of aligned_union?*/) {}
typedef std::array<base_ptr_t, sizeof...(Elements)> array_t;
const array_t GetArray();
private:
const array_t array_;
// Use tuple to store actual memory?
const std::tuple<Elements...> memory_store_0_;
// Use array of aligned_union's to store (perhaps memory inneficient compared
// to tuple) ??
std::array<std::aligned_union_t<0, derived_t...>, sizeof...(derived_t)>
memory_store_1_;
};
template <size_t N>
void Foo(const std::array<const BaseInterface *, N> &arr) {
// Do something interesting
}
int main() {
// Intended usage
BaseHandler<const BaseInterface *, Derived1, Derived2> handler(Derived1(),
Derived2());
auto arr = handler.GetArray();
Foo(arr);
}
Некоторые из обходных путей, которые я исследовал и которые мне не понравились, включают;
- Создание функционального не универсального c вспомогательного класса / функции, содержащего
static const std::array<X,X>
например,
const std::array<BaseInterface*,2> MakeResourceList() {
// Static lifetime, i.e. will not be destroyed when out of scope
static const Derived1 a();
static const Derived2 b();
std::array<BaseInterface*,2> result = {&a,&b};
return result;
}
Создание всех ресурсов и их ручная передача в массив. Приводит к раздуванию кода. Использование глобальных переменных для всех созданных ресурсов.