Могу ли я вызвать ошибку компиляции на «слишком мало инициализаторов»? - PullRequest
3 голосов
/ 07 сентября 2010

Я использую агрегатный инициализатор для настройки блока статических данных для модульного теста.

Я хотел бы использовать размер массива в качестве ожидаемого количества элементов, но это может завершиться ошибкой, если предоставлено слишком мало инициализаторов:

my_struct_type expected[14] =
{
    { 1.234, 0, 'c' },
    { 3.141, 1, 'z' },
    { 2.718, 0, 'a' }
};

Это не дает ошибки компилятора в Visual Studio 2008.

Я бы хотел использовать его так:

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);
}

, но, поскольку у меня нет гарантии времени компиляции в 14 пунктов, это запускает конец массива конец предоставленных значений и инициализированные по умолчанию значения.

Могу ли я как-то принудительно установить количество инициализаторов агрегатных массивов во время компиляции?

Ответы [ 5 ]

5 голосов
/ 07 сентября 2010

На самом деле он не запускается в конце массива, потому что компилятор инициализирует по умолчанию все элементы массива, которые вы сами не инициализировали.

Если вы пытаетесь убедиться, что у вас есть определенное количество настроенных инициализаторов, я не уверен, как это сделать.

Если вы просто хотите убедиться, что в массиве указано количество элементов, которые у вас есть:

my_struct_type expected[] =
{
    { 1.234, 0, 'c' },
    { 3.141, 1, 'z' },
    { 2.718, 0, 'a' }
};

сделает свое дело. Затем просто используйте sizeof(expected) / sizeof(expected[0]), чтобы получить общее количество элементов массива.

4 голосов
/ 07 сентября 2010

Во-первых: для этого может быть предупреждение. Вы пробовали компилировать на самом высоком уровне предупреждения?

Тогда: если вы меняете, какое значение вычислено, а какое - буквально, вы можете вызвать ошибку времени компиляции:

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 );
1 голос
/ 07 сентября 2010

ИСО / МЭК 14882 (Первая редакция 1998-09-01) в с.8.5.1.7 гласит следующее:

Если в списке меньше инициализаторов, чем элементов в агрегате, то каждый элемент, не инициализированный явно, должен инициализироваться по умолчанию (8.5).[Пример: struct S {int a;char * b;int c;};S ss = {1, "asdf"};инициализирует ss.a с 1, ss.b с "asdf", а ss.c со значением выражения формы int (), то есть 0.]

Проще говоря,ответа на ваш вопрос нет.

1 голос
/ 07 сентября 2010

Только ради ответа без ускорения ...

Вы можете добавить требование инициализации, изменив 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 все еще является совокупностью, но это не POD.

0 голосов
/ 07 сентября 2010

Согласно msdn , если указано меньшее количество инициализаторов, остальные элементы инициализируются с 0, поэтому код должен работать, тем не менее.

...