我想创建具有可变长度元素数组的对象,并使它们在基类/派生类意义上兼容。在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";
你可以用一个公共基类来实现,但这是必要的吗?我只想使用foo1
和foo2
,其中每个对象都知道其数组的长度。
我的应用程序适用于运行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
}
}