【发布时间】:2022-01-20 14:41:48
【问题描述】:
背景
对于嵌入式项目,我想要一个带有结构列表的类。这个列表在编译时是已知的,所以我不应该为此求助于动态内存分配。
但是,如何创建一个封装此数组的结构/类,而不必将其大小用作模板参数?
模板
我的第一个想法就是这样做:
struct Point {
const uint16_t a;
const double b;
};
template<size_t n>
struct Profile {
Array<Point, n> points;
Profile(const Array<Point, n> &points) : points(points) {}
};
这里,Profile 是存储/封装点数组(2 成员结构)的类。 n,数组的大小,是模板参数。
我正在使用数组的this 实现,类似于std::array,顺便说一句,因为我无法访问这个嵌入式平台上的 STL。
但是,没有,我有另一个使用这个 Profile 的类,现在也必须对其进行模板化,因为 Profile 是使用数组大小进行模板化的:
template<size_t n>
class Runner {
private:
const Profile<n> profile;
public:
Runner(const Profile<n> &profile) : profile(profile) {};
void foo() {
for(auto point : profile.points) {
// do something
}
}
};
可以看出,这个Runner 类在Profile 上运行并对其进行迭代。必须模板化Runner 本身并不是什么大问题,但是这个Runner 又被我项目中的另一个类使用,因为这个另一个类调用Runner::foo()。现在我也必须为该类模板!以及使用该类的类等。
这已经失控了!最初只使用一个模板参数来指定大小,现在在我的整个应用程序中传播。因此,我认为这不是一个好的解决方案。
问题
有没有办法在Profile 或Runner 中“隐藏”数组的大小? Runner 只需要对其进行迭代,因此大小原则上应该只影响它的实现,而不影响它的公共接口。不过,我该怎么做呢?
另外,我是否可以完全避免手动指定n,而只需将数组传递给Profile 的构造函数并让编译器计算出它有多大?当然是在编译时。我觉得这应该是可能的(考虑到这个数组在编译时是已知的),但我不知道具体如何。
其他方法
宏
我可以写一个类似的宏
#define n 12
并将其包含在Profile.h 和我实例化Profile 的地方。不过这感觉很脏,我想避免使用宏。
矢量
我可以通过使用 std::vector(或等效项)来避免这种大惊小怪,但这是在运行时分配在堆上的,我想在这里避免这种情况,因为它不应该是必需的。
【问题讨论】:
-
您需要多少种不同的尺寸?
-
另外,数组的这种实现似乎允许存储少于最大元素的元素(不像
std::array),也许只使用您将使用的数组的最大大小就足够了?跨度> -
什么时候你才真正知道数组的大小?例如,如果
Runner总是需要一个Profile和一个大小为12的数组,那么它可以使用Profile<12>,如果你需要Runners 和不同大小的Profiles,那么将Runner设为模板不会'听起来太糟糕了 -
@Yksisarvinen 还不知道。我只想要一个可以使用任意大小的
Profile类。 -
不使用大小为
n的普通旧数组的原因是什么,其中n是一个普通的旧整数常量?太容易了?太难读了?