Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating Template Parameters at Compile Time

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!

like image 830
Sam Cristall Avatar asked Nov 13 '22 08:11

Sam Cristall


1 Answers

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__)> \
{};
like image 112
Daniel Frey Avatar answered Nov 15 '22 05:11

Daniel Frey