Подтвердить что ты не робот

Размер элемента объединения С++ на основе другого размера элемента

Рассмотрим следующий фрагмент кода:

struct S
{
    union
    {
        int arr1[10];
        char arr2[sizeof(arr1)];
    };
};

Он успешно компилируется с gcc 4.9.2 в режиме С++ 03 и С++ 11. Однако, когда я изменяю S как шаблон следующим образом:

template <size_t N>
struct S
{
    union
    {   
        int arr1[N];
        char arr2[sizeof(arr1)];
    };  
};

Я получаю следующий вывод ошибки:

error: int S<10ul>::<anonymous union>::arr1 [10]’ is inaccessible

int arr1[N];

error: within this context

char arr2[sizeof(arr1)];

Clang компилирует обе версии только в режиме С++ 11. Мне любопытно, что здесь правильное поведение. Может быть, я должен явно указать, что размер arr2 sizeof(int) * N?

4b9b3361

Ответ 1

Ваш союз анонимен. Таким образом, компилятор создаст arr1 и arr2 на уровне класса. Из-за этого char arr2[sizeof(arr1)]; не будет правильно относиться к arr1.

Вот обходной путь:

template <size_t N>
struct S
{
    union A
    {   
        int arr1[N];
        char arr2[sizeof(arr1)];
    };  
};

Скомпилируется здесь: https://ideone.com/JcvOYg

Называя объединение, мы запрещаем компилятору включать его напрямую. Затем он может правильно восстановить arr1.

Но это также означает, что arr1 и arr2 больше не являются членами S.

Наконец, Members can be defined in terms of other members, но последний должен быть "найден" компилятором.

Ответ 2

Вы можете сделать это:

template <size_t N>
class S
{
private:
    union
    {
        int arr1[N];
        char arr2[N*sizeof(int)];
    };
};