I've created a class that looks like an array, but rather than holding the data in the program itself, it streams the byte from a file (to reduce RAM impact). Now I've got all this working, but the programmer has to define the class using the following:
#define CreateReadOnlyBlock(name, location, size, ...) \
template<> \
const unsigned int ReadOnlyBlock<location, size>::Data[] \
__asm__( ".readonly__" #location "__" #name) \
= { __VA_ARGS__ }; \
ReadOnlyBlock<location, size> name;
Example:
//A read only array of {0, 1, 2, 3}
CreateReadOnlyBlock(readOnlyArray, 0, 4, 0, 1, 2, 3);
Note that this is for an embedded processor, and the asm directive goes through a tool in the assembler to create the read-only-file.
So here's my question: how can I eliminate the "location" and "size" variables? I hate that the programmer has to type those in manually, and would much prefer some way of generating those at compile-time. So instead of the programmer needing to type:
//A read only array at location 0 of {0, 1, 2, 3}
CreateReadOnlyBlock(readOnlyArray1, 0, 4, 0, 1, 2, 3);
//A read only array at location 4 of {4, 5, 6, 7}
CreateReadOnlyBlock(readOnlyArray2, 4, 4, 4, 5, 6, 7);
They could just type:
CreateReadOnlyBlock(readOnlyArray1, 0, 1, 2, 3);
CreateReadOnlyBlock(readOnlyArray2, 4, 5, 6, 7);
And the appropriate constants would be generated. Basically I'm looking for some way to generate and place these constants based on previous definitions at compile time. C++11 is fair game, I'm just not terribly familiar with it (something with constexpr seems plausible?). Also, C-Preprocessor is okay too if it doesn't make it uglier than it already is. Is this possible?
EDIT for clarity:
In the ReadOnlyBlock class there is this method:
template<const int _location, const int _size> class ReadOnlyBlock
{
...
unsigned int operator[] (size_t index)
{
return LoadFromROM(index + _location);
}
}
There is an intrinsic interdependence between the location variable and the ROM file that I cannot think of how to break. I do have complete control over the tool chain as well, however, but I need a way to pass the assembler tool how to construct the file as well as indicate to the C++ code where the blocks lie in the file.
Another EDIT:
The file and its blocks can be quite large, as much as 1k words, so a lot of preprocessor magic might collapse given that. Also, thanks everyone for the help so far!
I still don't see the full solution for generating the name (that #location
fragment), but for the rest, I guess you could use something like this:
template< std::size_t Line >
struct current_location : current_location< Line - 1 > {};
template<>
struct current_location< 0 > : std::integral_constant< std::size_t, 0 > {};
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
#define CreateReadOnlyBlock(name, ...) \
template<> \
const unsigned int ReadOnlyBlock< \
current_location<__LINE__-1>::value, NUMARGS(__VA_ARGS__) \
>::Data[] \
__asm__( ".readonly__" #name) \
= { __VA_ARGS__ }; \
ReadOnlyBlock<current_location<__LINE__-1>::value, \
NUMARGS(__VA_ARGS__)> name; \
template<> \
struct current_location<__LINE__> \
: std::integral_constant<std::size_t, \
current_location<__LINE__-1>::value+NUMARGS(__VA_ARGS__)> \
{};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With