c++ - 如何将堆栈分配的多态指针数组模板化为接口(interface),包括派生类型的相应指针?

标签 c++ embedded c++14

就上下文而言,我正在研究嵌入式高可靠性环境。在这种环境中实现的一些限制包括:

  1. 没有动态内存分配
  2. 需要符合 c++14 或更低版本
  3. 没有运行时类型信息

所以最终结果是我想要一个包含 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);
}

我探索过但不喜欢的一些解决方法包括;

  1. 创建包含 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;
}
  1. 构建所有资源并将它们手动传递到一个数组中。导致代码膨胀。
  2. 对所有构建的资源使用全局变量。

最佳答案

似乎您想将派生对象存储为元组,然后将该元组与将其转换为数组的函数应用:

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 在静态断言中。

关于c++ - 如何将堆栈分配的多态指针数组模板化为接口(interface),包括派生类型的相应指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59727607/

相关文章:

unit-testing - uC/OS 的单元测试 - II

c++ - clang std::isspace 编译错误

c++ - 在 QT for Windows 中使用 Win32 API

c++ - QT/C++ 关于访问 UI 文件的另一个问题

c# - 将 boolean 值更改为与初始值相反的值

java - 嵌入式系统中的一个客户端 - 多个服务器

c++ - 是 Foo* f = new Foo 好的 C++ 代码吗

将整数值转换为 ip 地址

c++ - 类方法的 SFINAE

c++ - 在现代 C++ 中,是否有等效于来自 python 的基于范围的 `enumerate` 循环?