如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
How to template a stack allocated array of polymorphic pointers to interfaces, including the corresponding pointee of derived type?
对于上下文,我正在研究一个嵌入式高可靠性环境。在此环境中实施的一些限制包括:
- 无动态内存分配
- 需要符合 c++14 或更低 版本
- 无运行时类型信息
所以最终结果是我想要一个包含 BaseInterface 类型的指针const std::array
的类,该类可以包含一组堆栈分配的任意派生类。
请考虑下面的非完整示例。
注意: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);
}
我探索但不喜欢的一些解决方法包括:
- 创建一个包含
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;
}
- 构造所有资源并手动将它们传递到数组中。导致代码膨胀。
- 对所有构造的资源使用全局变量。
似乎您想将派生对象存储为元组,然后将该元组与将其转换为数组的函数一起应用:
template <class base_t, class... derived_t>
class BaseHandler {
static_assert(std::conjunction_v<std::is_base_of_v<base_t, derived_t>...>);
std::tuple<derived_t...> storage_;
public:
std::array<base_t*, sizeof...(derived_t)> GetArray() {
return std::apply([](derived_t&... deriveds){
return std:array<base_t*, sizeof...(derived_t)>{{&deriveds...}};
}, storage_);
}
};
为了清楚起见,这将 C++17 用于一些库内容,但所有这些都可以在 C++14 中实现,没有任何问题。
我还将模板参数从base_ptr_t
更改为base_t
,因为它使您的所有模板参数都相同"种类",并且您不必在静态断言中执行remove_pointer_t
。
相关文章:
- 存储模板类型以强制转换回派生<T>
- 在 C++ 中用派生类型重写成员函数
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 在 C++ 中将对象转换为派生类型
- 如何检查派生类的类型?(C++实例)
- 创建派生自可变参数模板包的类型元组
- C++如果采用类类型的函数被传递派生类型,有没有办法给出错误?
- 返回派生类型时出现协变类型错误
- 静态自动 constexpr t = { "red" , "black" , "green" } 是什么类型;派生到?
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- 在从仅移动类型派生的类中定义析构函数在使用 std::vector emplace_back或push_back创建时会
- (C++);动态决定函数的类型(派生类)
- 如何使variadic模板类方法以函数指针为参数,类型派生自函数模板
- 如何防止从 c++03 中的类型派生
- 如何为从特定类型派生的类型专门化模板
- 为什么在返回从函数的返回类型派生的类型本地对象时不选择 move 构造函数?
- 如何在模板类型中强制静态成员初始化?或如何获取从模板类型派生的所有类的计数
- 有没有任何方法可以从C++中的成员指针类型派生对象类型
- 在c++中基于另一个变量类型派生一个变量类型