tavalin:
Passing the array in seems to only be half the battle. How do I assign the array to a field in rfm69_node?
I'm not sure what the variable declaration in rfm69_node.h needs to look like.
I was waiting for you to ask this question.
When using arrays as parameters the length must be known (at compile time), like my article mentions. Without it all you declare is a pointer. This shouldn't be a problem as you cannot change the length of an array. User input will not make a difference, the array is still a certain size. And if you use dynamic memory, you'll have to use a run-time approach (new/malloc returns a pointer, so the array information is already lost).
The alternative is to store a pointer and length like others mentioned, this is defeating the benefit of using the template, however i'll show it for completeness as it shows the evolution between each method:
struct rfm69_node{
template< long N >
void setDevices( Device (&devices)[N] ) {
ptr = +devices;
count = n;
}
Device *ptr;
int count;
};
To overcome forcing the array to a pointer and using extra memory to store something that is already known we need to move the template to the class, rather than the single function.
template< long N >
struct rfm69_node{
void setDevices( Device (&devices)[N] ) {
array = &devices;
}
Device (*array)[N];
};
//Usage...
Device array[10];
rfm69_node< 10 > thing;
thing.setDevices( array );
As you can see the variable is a pointer so when using 'array' you need to dereference it (*array) and return to the actual array.
To use a reference you must use the constructor to initialize it, this means the array must be passed when the class is created.
template< long N >
struct rfm69_node{
rfm69_node( Device (&devices)[N] ) : array(devices) {}
Device (&array)[N];
};
//Usage...
Device array[10];
rfm69_node< 10 > thing( array );
And now the array is associated when the class is created (the elements can be assigned later if wanted). If the array should belong to the class, the separation of the array and class is just an additional step for a user, which is basically combining them in their own code. This can be avoided.
If you construct your class as a POD, you can take advantage of the brace-enclosed-initializer syntax and get rid of the reference copying and allow users to setup the class in a single step.
I have replaced the type Device with int so the usage makes sense.
template< long N >
struct rfm69_node{
int array[N];
};
//Usage
rfm69_node< 4 > thing = {{ 1, 2, 3, 4 }};
Now setDevices has basically been implemented in zero lines of code. As a POD cannot have private members, the array is still directly accessible (thing.array).