... с конструктором, не разрешенным в объединенной задаче - PullRequest
8 голосов
/ 16 мая 2011

Мне очень нужно найти решение для следующей проблемы:

namespace test
{
    template <int param = 0> struct Flags
    {
        int _flags;

        Flags()
        {
            _flags = 0;
        }

        Flags(int flags)
        {
            _flags = flags;
        }

        void init()
        {

        }
    };

    union example
    {
        struct
        {
            union
            {
                struct
                {
                    Flags<4096> f;
                }p1; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p1' with constructor not allowed in union

                struct 
                {
                    Flags<16384> ff;
                }p2; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p2' with constructor not allowed in union
            }parts;

            byte bytes[8];
        }data;

        int data1;
        int data2;
    }
}


Обидно, что если я добавлю теги к структурам p1 и p2, код скомпилируется, но члены f & ff будут недоступны:

...
struct p1
{
    Flags<4096> f;
};

struct p2
{
    Flags<4096> ff;
};
...

void test()
{
    example ex;
    ex.data.bytes[0] = 0; //Ok
    ex.data.parts.p1.f.init(); //error: invalid use of 'struct test::example::<anonymous struct>::<anonymous union>::p1'
}


Можно ли как-нибудь заставить эту работу работать?

Ответы [ 3 ]

9 голосов
/ 16 мая 2011

Как сказал @Als, union не может определить не POD как данные члена, есть одна альтернатива.Вы все еще можете определить указатель на не POD как данные члена объединения.

Так что это разрешено:

union
{
   struct
   {
      Flags<4096> *pf; //pointer to non-POD
   }p1;
   struct 
   {
      Flags<16384> *pff; //pointer to non-POD
   }p2;
}parts;

Но тогда Boost.Variant лучшая альтернатива.

7 голосов
/ 16 мая 2011

Текущий стандарт C ++ не допускает не-POD типы внутри союзов.Следовательно, вы получаете эту ошибку компилятора из gcc.
Вместо использования объединений C, вы должны использовать boost::variant.Проверьте документацию здесь .

Чтобы добавить к вышесказанному:
Новый стандарт C ++ (C ++ 0x) добавляет новую функцию под названием Unrestricted Unions , который поддерживает хранение типов не POD в Union.

0 голосов
/ 16 мая 2011

C ++ стандарт 2003 не допускает этого (из Стандарта 9.5):

Объект класса с нетривиальным конструктором (12.1), нетривиальным конструктором копирования (12.8)нетривиальный деструктор (12.4) или нетривиальный оператор присваивания копии (13.5.3, 12.8) не может быть членом объединения, а также не может содержать массив таких объектов.

Но C ++ 0x позволяет это, однако вам нужно определить свой собственный конструктор, потому что конструктор по умолчанию будет объявлен как удаленный, если вы не определите свой собственный.

Начиная с N3291 9.5:

Если какой-либо элемент не статических данных объединения имеет нетривиальный конструктор по умолчанию (12.1), конструктор копирования (12.8), конструктор перемещения (12.8), оператор назначения копирования (12.8), оператор назначения перемещения (12.8),или деструктор (12.4), соответствующая функция-член объединения должна быть предоставлена ​​пользователем, или она будет неявно удалена (8.4.3) для объединения.

Другие люди предложили Boost.Variant.Для простого исправления просто удалите конструктор из класса Flag.Хотя вам нужно инициализировать его вручную всякий раз, когда вы инициализируете объект объединения, это не будет сбивать с толку, потому что объединение - это, по сути, функция Си.

...