Background
For an embedded project, I want a class that takes a list of structs. This list is known at compile-time, so I shouldn't have to resort to dynamic memory allocation for this.
However, how do I make a struct/class that encapsulates this array without having to use its size as a template parameter?
Templates
My first idea was to do exactly that:
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) {}
};
Here, Profile is the class that stores/encapsulates the array of points (the 2-member structs). n, the size of the array, is a template parameter.
I'm using this implementation of Array, similar to std::array, btw, because I don't have access to the STL on this embedded platform.
However, no I have another class that uses this Profile that now also has to be templated because Profile is templated with the size of the array:
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
}
}
};
As can be seen, this Runner class operates on a Profile and iterates over it. Having to template Runner is not that much of an issue by itself, but this Runner in turn is used by another class in my project, because this other class calls Runner::foo(). Now I have to template that class as well! And classes that use that class, etc.
That's getting out of hand! What started with just one template parameter to specify the size, now propagates through my entire application. Therefore, I don't think this is a good solution.
Question
Is there a way to 'hide' the size of the array in Profile or Runner? Runner only needs to iterate over it, so the size should in principle only affect its implementation, not its public interface. How would I do that, though?
Also, can I avoid having to manually specify n at all, and just pass an array to Profile's constructor and let the compiler figure out how big it is? At compile-time, of course. I feel like this should be possible (given this array is known at compile-time), but I don't know how exactly.
Other approaches
Macros
I could write a macro like
#define n 12
and include that in both the Profile.h and the place where I instantiate a Profile. This feels dirty though, I and would like to avoid macros.
Vector
I could avoid this fuss by just using a std::vector (or equivalent) instead, but that is allocated at run-time on the heap, which I would like to avoid here since it shouldn't be necessary.