在不使用动态分配的情况下,C99复合文字的C++14替代方案是什么



我正在使用C++14开发一个带有MPU的ARM处理器的嵌入式系统,我想在初始化期间减少动态分配的数量,因为我更想知道链接时使用的确切内存量。

在C99中,您可以使用复合文字在堆栈或全局范围上分配内存,请参阅以下无意义代码,它在编译时在结构中分配结构:

struct Foo {
struct Foo* next;
};
struct Foo *bar = {
&(struct Foo){
&(struct Foo){ NULL }
}
};

不可能使用任何GCC或Clang扩展来解决这个问题,只能使用纯C++14代码。

我发现,模仿这种行为的唯一简单方法是使用lambda函数。然而,这个解决方案是不可重入的。

struct Foo* bar = [](){
static struct Foo bar = {
static struct Foo bar = { nullptr };
return &bar;
}();
return &bar;
}();

lambda解决方案适用于我的情况,我可以使用宏使其使用起来更舒适,但如果我想将数据结构放在堆栈上,它就不是一个解决方案。

解决这个问题的最佳C++方法是什么(不使用动态分配(?

我目前试图解决的问题是派生类的树,我想在编译时分配它。

我试图在想象中的C++代码中实现的目标:

RootClass* b = &(DerivedClass1){ &(DerivedClass2){10},
&(DerivedClass2){20},
&(DerivedClass1){ &(DerivedClass0){} }
};

我试图在想象中的C++代码中实现的目标:

好吧,永远不会工作。没有要求这些派生类中的任何一个与基类大小相同,因此不可能在基类上进行指针运算(即使C++允许在基类上对指向元素类型为派生类的数组的指针进行指针运算。而不允许(。

如果你处理的是单一类型的T,那么你可以这样做:

T ts[] = {<initializers>};

您可以根据需要使用ts。但这只适用于适当的数组。

现在,如果你想做派生类的事情,你可以总是使用tuple作为派生类元素的容器,然后构建一个指向基类元素的指针数组,这样你就可以从一个元素迭代到另一个元素。C++14让这有点麻烦,因为它需要在tuple类型本身中列出类型,但C++17的类模板参数推导使它更容易理解:

auto tpl = tuple(DerivedClass2{10}, DerivedClass2{20}, DerivedClass1{DerivedClass0{}});

C++14版本只是重复这些类型。

构建数组需要一些模板元编程技术:

template<typename BC, typename Tpl, std::size_t ...ixs>
auto GetBaseClassArrayHelper(Tpl &tpl, std::index_sequence<ixs...>)
{
return std::array<BC*, std::tuple_size<Tpl>::value>{static_cast<BC*>(std::get<ixs>(tpl))...};
}
template<typename BC, typename Tpl>
std::array<BC*, std::tuple_size<Tpl>::value> GetBaseClassArray(Tpl &tpl)
{
return GetBaseClassArrayHelper<BC>(tpl, std::make_index_sequence<std::tuple_size<Tpl>::value>{});
}

现在,这不允许您将BaseClass*++转换为不同的BaseClass*。为了做到这一点,您需要在指针数组中有一个指针,一个BaseClass**

最新更新