阵列模板兼容性的好模式是什么



我想创建具有可变长度元素数组的对象,并使它们在基类/派生类意义上兼容。在C中,可以在struct的末尾放置一个不确定的数组,然后对对象进行malloc以包含完整的数组:

struct foo {
int n;
double x[];
} ;
struct foo *foo1 = (foo *)malloc( sizeof( foo ) + sizeof( double[4] ) );
struct foo *foo2 = (foo *)malloc( sizeof( foo ) + sizeof( double[100] ) );

在c++中,你似乎可以做到:

template <unsigned I>
class foo {
public:
int n;
double x[I];
} ;

但是:

auto foo1 = new foo<4>( );
auto foo2 = new foo<100>( );
if (foo1 == foo2) cerr << "incompatible pointers";

你可以用一个公共基类来实现,但这是必要的吗?我只想使用foo1foo2,其中每个对象都知道其数组的长度。


我的应用程序适用于运行FreeRTOS的ESP32微控制器。由于不同内存块的能力不同(有些速度较慢,有些不能包含可执行代码,有些不能通过DMA访问,等等(,它具有有限的非虚拟RAM和稍微复杂的分配系统。因此,为一个对象的多个块分配多个块(例如,最后为double的数组使用std::vector(变得复杂。

在对象构造时,我知道double数组的长度,但我希望标头和数组位于单个分配的内存块中(这样它就可以具有我稍后需要的特性(。

C风格的方法会很好,但最好有C++功能,比如在数组上迭代(对于各种对象,每个对象都有不同数量的double(。此外,本机C++解决方案将允许我在x[]数组中拥有对象,而不是在原始分配内存中随意放置new。例如:

auto a[] = { new foo<5>( ), new foo<10>( ), new foo<15>( ) };
for (auto i : a)
for (auto j : i.x)
cout << log10( j );    // prints 40 logs of doubles

(我预计这会有C++语法错误,但希望它能传达这个想法。如果我能把所有的foo放入一个公共容器中,我就能弄清楚它的语法。(

作为一名低级C++开发人员,我完全理解您的需求,遗憾的是,无论是否使用模板,标准C++中都无法替代灵活的数组成员。您必须通过编译器扩展继续使用灵活的数组成员。

它们没有包含在语言中,因为以目前的形式,它们本质上是一个黑客。它们在继承或组合方面做得不好。

模板的问题在于,灵活的数组版本有一种常见类型的各种大小的数组。这意味着你可以将它们放在数组中,让非模板函数将它们作为参数等:

foo* make_foo(int n);
foo* foos[] = { make_foo(1); make_foo(2); make_foo(3); }; // ok
void take_foo(foo*);

对于模板版本,类型foo<1>foo<2>完全不相关,因此不能将它们放在数组中,也不能使用非模板函数:

template <int N>
foo<N>* make_foo();
auto foos[] = { make_foo<1>(), make_foo<2>(), make_foo<3>() }; // ill-formed
template <int N>
void take_foo(foo<N>*);

std::array在这个讨论中没有帮助,从一个继承仍然会有不相关类型的问题。

然而,由于这仍然是C++(尽管是非标准的(,您至少可以拥有一些额外的细节:

template <class T>
struct flex_array {
int n;
T data[];
T* begin() { return &data[0]; }
T* end() { return begin() + n; }
};

void iterate(flex_array<double>& f) {
for (double j : f) {
cout << log10(j); // print however many doubles are in f
}
}

最新更新