I was working on a small macro project that requires me to pass a 2 dimensional array literal to one of my macros like so: myMacro({{0, 1, 2}, {2, 1, 0}}). Without having to pass the size of the array literal to the macro, is there a way to have it expand to the following: int[2][3] = { {0, 1, 2}, {2, 1, 0} } or something equivalent (any initialization that preserves the shape of the array will work)? Thanks in advance for any help
2 Answers
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define VA(...) __VA_ARGS__
#define TRANS(r, data, elem) { VA elem},
#define myMacro(name, arg)\
int name[BOOST_PP_TUPLE_SIZE(arg)][BOOST_PP_TUPLE_SIZE(BOOST_PP_TUPLE_ELEM(0,arg))] = \
{ BOOST_PP_SEQ_FOR_EACH(TRANS, , BOOST_PP_VARIADIC_TO_SEQ arg)}
int main(){
myMacro(a, ((1,2,3),(4,5,6)) );//=>int a[2][3] = { { 1,2,3}, { 4,5,6}, };
return 0;
}
4 Comments
NerdicViking
Oh, sorry, I didn't see this answer until now. Does this work in C (pre-99, preferably)? I thought that Boost was C++ only?
BLUEPIXY
@NerdicViking part of the preprocessor of boost will work even C. The decision to work with C99 previous C can not be guaranteed, but it was confirmed work with VC2010.
Santeri Paavolainen
@BLUEPIXY cool, I didn't know Boost had those kinds of macros. I checked with GCC, and C99 level is required (earlier will fail in preprocessor).
BLUEPIXY
@SanteriPaavolainen yes, variadic macro seems to be from the C99.
If you have an upper limit for the second dimension then you could use sentinel values such as:
#include <stdio.h>
#define MAXCOLUMNS 20
#define VALUE {{0,1,2,-1},{2,3,4,-1},{0,0,0,0,1,-1},{-1}}
int main()
{
int v[][MAXCOLUMNS] = VALUE;
int x, y;
for (y = 0; v[y][0] != -1; y++)
for (x = 0; v[y][x] != -1; x++)
printf("[%d,%d] = %d\n", x, y, v[y][x]);
return 0;
}
This will print out the values without knowing the exact dimensions beforehand. Is this something you are trying to achieve?
Edit: @BLUEPIXYs solution doesn't require knowing or guessing maximum dimensions, on the other hand this works with older C versions (not a big concern, though).
2 Comments
NerdicViking
An upper value could work, but only for the first element. The code should be able to guess how many different rows there are (one to correspond to each element of an enum created by another macro, which I can add a
ENUM_SIZE value to the end of to count the rows, but the length of the individual columns is unknown.NerdicViking
The solution I went with is guessing how big it might get. I was trying to do something with:
#define VA_NUM_ARGS(_1, _2, _3, _4, N ...) N but that only works up to 63 and may also be wrong depending on what number is passed, so I couldn't use that.
myMacro{{1, 2, 3, 4}, {5, 6, 7, 8}}). There is no upper bound, but the number of columns will always be the same for each row.__VA_ARGS__to a variable for later usage.