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?
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 );
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.
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.