I am using an aggregate initializer to set up a block of static data for a unit test.
I would like to use the array size as the expected number of elements, but this can fail if too few initializers are provided:
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
This gives no compiler error in Visual Studio 2008.
I would like to be able to use it as such:
const unsigned expected_size = sizeof(expected) / sizeof(my_struct_type);
BOOST_CHECK_EQUAL(points.size(), expected_size);
for( int i = 0; i < expected_size; i++ )
{
BOOST_CHECK_EQUAL(points[i].value, expected[i].value);
BOOST_CHECK_EQUAL(points[i].count, expected[i].count);
BOOST_CHECK_EQUAL(points[i].sym, expected[i].sym);
}
but because I don't have a compile-time guarantee of 14 points, this runs off the end of the array end of the provided values and into the default-initialized values.
Can I somehow enforce the number of aggregate array initializers at compile-time?
Actually it won't run off the end of the array, because the compiler will default-initialize all the elements of the array that you didn't initialize yourself.
If you're trying to make sure that you have a specific number of configured initializers, I'm not sure how to do that.
If you just want to make sure the array is the number of items you have:
my_struct_type expected[] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
Will do the trick. Then just use sizeof(expected) / sizeof(expected[0]) to get the total number of array elements.
First: There might be a warning for this. Have you tried compiling at the highest warning level?
Then: If you swap which value is calculated and which is literal, you could raise a compile-time error:
my_struct_type my_array[] = // <== note the empty []
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
BOOST_STATIC_ASSERT( sizeof(my_array)/sizeof(my_array[0]) == 14 );
Just for the sake of a non-Boost answer…
You can add an initialization requirement by modifying my_struct_type.
template< typename T >
struct must_be_initialized {
T value;
must_be_initialized( T const &v ) : value( v ) {}
// no default constructor!
operator T& () { return value; }
operator T const& () const { return value; }
};
struct my_struct_type {
must_be_initialized< double > f;
int i;
char c;
};
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
// error: no default constructor exists
};
my_struct_type is still an aggregate, but it is not POD.
ISO/IEC 14882 (First edition 1998-09-01) in p. 8.5.1.7 states the following:
If there are fewer initializers in the
list than there are members in the
aggregate, then each member not
explicitly initialized shall be
default-initialized (8.5). [Example:
struct S { int a; char* b; int c; }; S
ss = { 1, "asdf" }; initializes ss.a
with 1, ss.b with "asdf", and ss.c
with the value of an expression of the
form int(), that is, 0. ]
Simply, the answer to your question is no.
According to the msdn, if fewer initializers are specified, the remaining elements are initialized with 0, so the code should work nonetheless.
Related
I am using an aggregate initializer to set up a block of static data for a unit test.
I would like to use the array size as the expected number of elements, but this can fail if too few initializers are provided:
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
This gives no compiler error in Visual Studio 2008.
I would like to be able to use it as such:
const unsigned expected_size = sizeof(expected) / sizeof(my_struct_type);
BOOST_CHECK_EQUAL(points.size(), expected_size);
for( int i = 0; i < expected_size; i++ )
{
BOOST_CHECK_EQUAL(points[i].value, expected[i].value);
BOOST_CHECK_EQUAL(points[i].count, expected[i].count);
BOOST_CHECK_EQUAL(points[i].sym, expected[i].sym);
}
but because I don't have a compile-time guarantee of 14 points, this runs off the end of the array end of the provided values and into the default-initialized values.
Can I somehow enforce the number of aggregate array initializers at compile-time?
Actually it won't run off the end of the array, because the compiler will default-initialize all the elements of the array that you didn't initialize yourself.
If you're trying to make sure that you have a specific number of configured initializers, I'm not sure how to do that.
If you just want to make sure the array is the number of items you have:
my_struct_type expected[] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
Will do the trick. Then just use sizeof(expected) / sizeof(expected[0]) to get the total number of array elements.
First: There might be a warning for this. Have you tried compiling at the highest warning level?
Then: If you swap which value is calculated and which is literal, you could raise a compile-time error:
my_struct_type my_array[] = // <== note the empty []
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
};
BOOST_STATIC_ASSERT( sizeof(my_array)/sizeof(my_array[0]) == 14 );
Just for the sake of a non-Boost answer…
You can add an initialization requirement by modifying my_struct_type.
template< typename T >
struct must_be_initialized {
T value;
must_be_initialized( T const &v ) : value( v ) {}
// no default constructor!
operator T& () { return value; }
operator T const& () const { return value; }
};
struct my_struct_type {
must_be_initialized< double > f;
int i;
char c;
};
my_struct_type expected[14] =
{
{ 1.234, 0, 'c' },
{ 3.141, 1, 'z' },
{ 2.718, 0, 'a' }
// error: no default constructor exists
};
my_struct_type is still an aggregate, but it is not POD.
ISO/IEC 14882 (First edition 1998-09-01) in p. 8.5.1.7 states the following:
If there are fewer initializers in the
list than there are members in the
aggregate, then each member not
explicitly initialized shall be
default-initialized (8.5). [Example:
struct S { int a; char* b; int c; }; S
ss = { 1, "asdf" }; initializes ss.a
with 1, ss.b with "asdf", and ss.c
with the value of an expression of the
form int(), that is, 0. ]
Simply, the answer to your question is no.
According to the msdn, if fewer initializers are specified, the remaining elements are initialized with 0, so the code should work nonetheless.
I'm writing a program that allows the user to play sudoku puzzles. Each puzzle is a 2d array of structs, but I'm unable to intialize the array in one go. Is there any way to do this without needing to intialize each part of the structure for each element of the array? Here is some of my code.
class Sudoku {
protected:
struct Puzz {
int Ans;
// IsClue is used further in the program so the user cannot change the clues given.
bool IsClue;
};
Puzz Puzzle[9][9]; // I chose a 2D array so represent the 9 rows and columns of a sudoku puzzle
};
I've tried some of the following:
Puzzle[][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false}, //...etc, going on for each row
Puzzle[9][9] = // etc, etc, but I get an error saying "Expected an expression
Is the only way to initialize each element to do
Puzzle[x][y].Ans = x; Puzzle[x][y].IsClue = true/false;?
The problem is that you try to assign to an array, and it's simply not possible. You need to actually initialize it, which is something completely different.
If you don't mind writing lot of lines that are almost the same, then you could use a constructor member initializer list. Like e.g.
Sudoku::Sudoku()
: Puzzle{{...}, {... }, ... }
{}
If only a few structures in the arrays differ from some default values, then you could set all entries in the arrays to the same default value, using e.g. std::fill and then change those few entries that have special values.
Here's an example showing how a 2 x 2 array can be initialized. I'll leave it to you to extend that to a 9 x 9 array.
class Sudoku {
Sudoku();
protected:
struct Puzz {
int Ans;
bool IsClue;
};
Puzz Puzzle[2][2];
};
Sudoku::Sudoku() : Puzzle{{{0, false}, {1, true}}, {{2, false}, {3, true}}}
{
}
Having said that, it might be easier to create a default constructor of Puzz which does the sensible thing for most objects and then modify only a select elements of Puzzle in Sudoku's constructor.
class Sudoku {
Sudoku();
protected:
struct Puzz {
int Ans;
bool IsClue;
Puzz() : Ans(0), IsClue(false) {}
};
Puzz Puzzle[2][2];
};
Sudoku::Sudoku()
{
// Change specific elements of Puzzle
}
You can initialize with an initializer list in c++11 or higher:
Puzz Puzzle[2][2] = {
{ {8, true}, {9, false} },
{ {10, true}, {11, false} }
};
If in a class you can default construct it the same way:
class PuzzHolder {
PuzzHolder() : Puzzle{
{ {8, true}, {9, false} },
{ {10, true}, {11, false} }
} { }
Puzz Puzzle[2][2];
};
Although, if it is very big, this might get pretty messy. So the final approach could be to initialize it in a loop.
Live example.
To initialize a two-dimensional array, use a for-loop. As in:
for (int i = 0; i < row_count; i++) {
for (int j = 0; j < col_count; j++) {
item[i][j] = initial_value;
}
}
If you want to use an initializer list like in the above, you can do so by simply wrapping each instance of the struct in brackets. However, initializing your sodoku board with a literal is not a particularly scalable approach to generating a sodoku board for the player. That is, instead of:
Puzzle puzz[9][9] = {{0, false, 8, true, 0, false, 6, true, 7, true, 0, false, 0, false, 0, false, 0, false, ...}};
You would use:
Puzzle puzz[9][9] = {
{ // First row
{0, false}, // first column
{8, true}, // second column
...
},
{ // Second row
...
},
...
};
Since this is C++, though, you may wish to consider representing your board using nested vectors (that is vector<vector<Cell>>). While this may be overkill, especially for a Sodoku board (especially if it is always 9x9), that will allow you to more easily represent non-standard board sizes, and the vector data structure comes with the ability to default initialize/fill all members with a pre-specifed value. As #paddy aptly notes in the comments, however, there are also other functions (like std::fill that can be used with ordinary arrays to handle common use cases.
I'm porting some C code to C++ and I can't resolve a particular issue dealing with sub-object inititialization.
The following code is an example of what I mean :
#include <stdio.h>
#define MY_INDEX 1
#define MY_OTHER_INDEX 3
/* Structure declaration */
struct my_struct
{
int a;
int b;
int c;
};
/* Array declaration and initialization */
struct my_struct my_array[] =
{
[0] = (struct my_struct) {0, },
[MY_INDEX] = ((struct my_struct) {
.a = 10,
.b = 20,
.c = 30
}),
[MY_OTHER_INDEX] = ((struct my_struct) {
.a = 42,
.b = 42,
.c = 42
})
};
/** Test code */
int
main(void)
{
unsigned int i;
for (i = 0; i < sizeof(my_array)/sizeof(struct my_struct); i++)
printf("Index %u: a=%d, b=%d, c=%d\n",
i, my_array[i].a, my_array[i].b, my_array[i].c);
return 0;
}
It can be compiled without warnings nor errors with gcc -ansi -Wall, although adding the -pedantic flag will throw some warnings stating that ISO C90 forbids specifying subobject to initialize.
The initialization of my_array will act like if :
Index 0 will have a,b,c = 0
Index 1 (MY_INDEX) will have a=10, b=20, c=30
Index 2 will also have a,b,c = 0
Index 3 (MY_OTHER_INDEX) will have a,b,c = 42
I really like this form of initialization, I find it concise and readable.
Using this syntax with C++ will result in GCC thinking I'm declaring a lambda function because of the [], and even without the index GCC tells me it expected primary-expression before 'struct'.
What would be an equivalent in C++ (even with the C++11 standard) ? The key point is to be able to specify the structure fields name in the initializer for readability (the real structure have dozen of integer fields and bitfields), being able to also see the index in the initializer would be a plus too.
C++ doesn't have all the special aggregate initializer syntax that C supports. Instead, say this:
my_struct my_array[] = { { },
{ 10, 20, 30 },
{ 42, 42, 42 },
};
You can't have "gaps" in arrays (not even in C, I think).
I have a 2D array which I declared part of the classes private members. When I call the constructor, I start assigning values to the 2D array. But every time I do so, I'm hit with an error C2059. To make sure nothing else was causing that error I commented out that line and the compiler finished putting together a binary file.
tried:
Variable[row] = { 0, 1, 2, 3};
Variable[row][] = { 0, 1, 2, 3};
Variable[row][4] = { 0, 1, 2, 3};
No luck, any clues. Thanks in advance.
This syntax is only to be used for the creation of the object.
int array[4] = {1, 2, 3, 4};
Once the array is created, you have to use a loop to assign values to it.
Here's a short example :
class A
{
int array[4];
public:
A()
{
// Here, array is already created
// You can _assign_ values to it
}
};
If you want to give it values when it's instantiated in the constructor, the only way is to use initialization lists. Unfortunatly, you can't do this with a static array.
See this this thread.
Unfortunately, we can't yet properly initialize arrays that are members of classes. I don't know exactly how yours is declared, but here's an example of what to do:
class X
{
int Variable[3][4];
public:
X()
{
const int temp[][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
const int sz = sizeof(Variable)/sizeof(**Variable);
std::copy(*temp, (*temp) + sz, *Variable);
}
};
Since your question is not clear enough, all I can do is demonstrating a simple example.
2D array is initialized as,
//you may "optionally" provide the size of first dimension
int arr[][4] = {
{1,2,3,4},
{11,12,13,14},
{21,22,23,24}
};
And is acessed as,
for ( int i = 0 ; i < 3 ; ++i )
{
for ( int j = 0 ; j < 4 ; ++j )
{
cout << arr[i][j] << endl;
}
}
Online demonstration at ideone : http://www.ideone.com/KmwOg
Are you doing similarly?
In GCC, I'm able to do this:
(CachedPath){ino}
inode->data = (struct Data)DATA_INIT;
where:
struct CachedPath
{
Ino ino;
};
typedef int8_t Depth;
struct Data
{
Offset size;
Blkno root;
Depth depth;
};
#define DATA_INIT {0, -1, 0}
MSVC gives the following error for these kind of casts:
error C2143: syntax error : missing ';' before '{'
How can I do this in MSVC? Further note that the code has been converted from C99, where I used designated initializers for this, and then cast it similarly. Any clarity on how these various features relate between C99, and MSVC/GCC implementations of C++ is appreciated.
The construct (Type){initialisers} is not a cast operation, but it is the syntactic construct of a compound literal.
This is a C99 construct, which GCC also supports in its C++ compiler as an extension. As far as I can determine, compound literals are not supported up to and including MSVC 2012, in either its C or C++ mode. The support in C mode was introduced later, in MSVC 2013. In C++ mode it is still not supported and I believe it is unlikely support will be added.
For MSVC 2012 and older, the alternatives for this construct are
Explicitly declare and initialise a temporary object of the desired struct type and use that instead of the compound literal in the assignment
Instead of doing a single assignment with the compound literal, use a separate assignment for each individual member.
MSVC is not conformant to C99 and only loosely conformant to previous versions of the C standard. I know no way to do what you want syntactically with MSVC, but the same effect can be obtained by using static const structs instead of anonymous compound literal constants, and local struct variables that are initialized with the correct values instead of anonymous compound literals that are nonconstant.
The idea behind this approach is that a C99 compound literal is (at least nearly) equivalent to a local variable of the same type at the same scope, initialized with the contents of the braces. Using static const structs in the case where the data is constant is just an optimization (it will likely produce smaller/faster code than the C99 compound literal approach).
Visual Studio, since VS2013, supports Compound literals and Designated initializers.
Which C99 features are available in the MS Visual Studio compiler?
Example:
// main.c
#include <stdio.h>
void func(int(*array)[3]);
int main()
{
// Designated initializers
int a[6] = { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]
struct point { int x, y; };
struct point p = { .y = 13, .x = 27 }; // x = 27, y = 13
union foo { int i; double d; };
union foo f = { .d = 4 }; // d = 4.0
struct point ptarray[5] = { [2].y = 34, [2].x = 42, [0].x = 58 };
// (58 0), (0 0), (42 34), (0 0), (0 0)
// Compound literals
int *a1 = NULL;
a1 = (int[6]) { [4] = 29, [2] = 15 }; // [0, 0, 15, 0, 29, 0]
struct point p1;
p1 = (struct point) { .y = 13, .x = 27 }; // x = 27, y = 13
union foo f1;
f1 = (union foo) { .d = 4 }; // d = 4.0
struct point *ptarray1 = NULL;
ptarray1 = (struct point[5]) { [2].y = 34, [2].x = 42, [0].x = 58 };
// (58 0), (0 0), (42 34), (0 0), (0 0)
int *p2 = NULL;
p2 = (int[2]) { -1 };
p2 = (int[]) { -73, 89, 92 };
func(&(int[]) { -73, 89, 92 });
return 0;
}
void func(int(*array)[3])
{
for (int i = 0; i < 3; i++) {
printf("%d ", (*array)[i]);
}
}
MSVC is a mix of standards, and is not fully compliant with most of them, thus, you'll probably need to use a default initializer/constructor, like so (C++ way):
#define DATA_INIT 0,-1,0
inode->data = Data(DATA_INIT);
struct Data
{
Offset size;
Blkno root;
Depth depth;
Data(Offset size, Blkno root, Depth depth) : size(size), root(root), depth(depth)
{
}
};