I would like to hold an array of integers in my struct
struct HPDF_TableAttributes
{
HPDF_REAL rows;
HPDF_REAL cols;
HPDF_REAL rowH;
HPDF_REAL colW;
HPDF_REAL tabX;
HPDF_REAL tabY;
HPDF_REAL tabH;
HPDF_REAL tabW;
HPDF_Font font;
HPDF_REAL fontSize;
int colRatios[]; /// HERE
};
It seems not matter how I do it, the compiler wishes me to to initialize it here? Must I do that? I am trying to do something along the lines of the following for usage.
HPDFTableAttributes oTACent;
oTACent.rows = 3; oTACent.cols = 3;
oTACent.rowH = 20; oTACent.colW = pageWidth-70/oTACent.cols;
oTACent.tabH = oTACent.rows * oTACent.rowH;
oTACent.tabW = oTACent.cols * oTACent.colW;
oTACent.tabX = 35; oTACent.tabY = pageHeight - oTACent.tabH - 45;
oTACent.font = fontTimesBold; oTACent.fontSize = 20;
oTACent.colRatios = [1, 1, 2]; /// HERE
Then I send these attributes to my function which makes me a table and uses the ratio of the values in this integer array to space columns along the same lines.
void CReport::putTableOnPdf(HPDF_Page page, HPDFTableAttributes tabAtt, array_2d<CString> tabDat)
{
// Table Outline
HPDF_Page_SetLineWidth (page, 1);
HPDF_Page_Rectangle (page, tabAtt.tabX, tabAtt.tabY, tabAtt.tabW, tabAtt.tabH);
// Table row lines
HPDF_REAL rowsPut = 0;
while(rowsPut < tabAtt.rows)
{
rowsPut++;
HPDF_Page_MoveTo (page, tabAtt.tabX, tabAtt.tabY + rowsPut*tabAtt.rowH);
HPDF_Page_LineTo (page, tabAtt.tabX + tabAtt.tabW, tabAtt.tabY + rowsPut*tabAtt.rowH);
}
// Table col lines
/*int colRatioSum = 0;
for(int i = 0; i < tabAtt.colRatios.length; i++)
colRatioSum += tabAtt.colRatios[i];
tabAtt.colW = tabAtt.colW / colRatioSum;*/ /// HERE
HPDF_REAL colsPut = 0;
while(colsPut < tabAtt.cols)
{
colsPut++;
HPDF_Page_MoveTo (page, tabAtt.tabX + colsPut*tabAtt.colW, tabAtt.tabY);
HPDF_Page_LineTo (page, tabAtt.tabX + colsPut*tabAtt.colW, tabAtt.tabY + tabAtt.tabH);
}
HPDF_Page_Stroke (page);
}
In C++ the size of an array is part of its type.* There's a special rule that allows an array declaration to deduce its size from the initializer, so you don't always have to write the type explicitly.
You can also write and use incomplete types in certain circumstances, but you can't do anything with them that requires a complete type.
So the problem here is that you're writing an incomplete type and doing something with it that requires a complete type (namely, declaring an object of that type). Adding an initializer is one way to declare the array's size and thus complete the type, which avoids the error.
If what you really want is to say "and the last field is a collection of ints," then you need to use a type that can represent that (again, arrays have a fixed number of elements). In C++ the most obvious solution is std::vector<int>
. Using std::vector
you can write your pseudo-code almost exactly:
oTACent.colRatios = {1, 1, 2};
Another option, which you might see but shouldn't write, is to use a pointer. C++ is defined such that you can use a pointer to an element of array similarly to an array. Since a pointer type doesn't include the array size, the same pointer type can be used with an array of any size.
* some compilers support variable length array members as an extension, where the size of the array is determined when the struct is initialized, but this isn't standard C++ and it still requires the size to be known at initialization (rather than from a later assignment, like in your pseudo code where you assign to the array). There's another extension called 'flexible arrays' where the last member can be declared without a size and then you manually allocate enough memory for the entire struct plus however large you want the array to be.