Инициализация чз {} сложной структуры можно или нет?
От: lolovo  
Дата: 12.12.19 14:41
Оценка:
Добрый день!

Необходима инициализация сложной структуры данных через {}, чтобы было красиво и удобно, без дробления инициализации (т.е. по частям — не надо)... Голову уже сломал над тем, что не так .

Сразу оговорка, для GNU GCC (я пытаюсь реализовать на нем) — если код не компилируется и выдает "internal compiler error: in reshape_init_class, at cp/decl.c", то необходим этот патч.

Итак, есть код:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <string.h>
#include <vector>

union _UVAR {
        bool _bool;
        char _char;
        int _int;
        std::string _string;
        std::vector<int> _intarr;
        double _float;
    long double _ldouble;
        ~_UVAR(){};
};

struct _DATA;
typedef std::map<std::string, _DATA> _CMDDATA;
struct _DATA {
        enum _TYPE{ NONE, INTARR, STRARR, INT, UINT, BOOL, LONG, ULONG, STRING, USTRING, CHAR, UCHAR, FLOAT } type;
        _CMDDATA children;
        union {
                bool _bool;
                char _char;
                int _int;
                std::string _string;
                std::vector<int> _intarr;
                double _float;
                long double _ldouble;
        };
        _DATA(const _DATA& _d) : type(_d.type), children(_d.children), _ldouble(_d._ldouble){}; //sizeof(long double) == sizeof(std::vector<int>) == 12 байт, т.е. копируем все данные, т.к. 12байт - макс размер
        _DATA(const _TYPE& _type, const _CMDDATA& chld, const _UVAR& _d): type(_type),children(chld),_ldouble(_d._ldouble){};
        ~_DATA(){};
};

int main()
{
        _CMDDATA d2 =           { 
                    {"str",  {.type=_DATA::STRING, .children={}, {._string="TEST"} } } ,
                                        {"test111", { .type=_DATA::BOOL, .children={}, {._bool=1} } },
                                        {"intarr", {.type=_DATA::INTARR,.children={}, {._intarr={1,2} } } },  // <----------- ПРОБЛЕМНОЕ МЕСТО. Не компилируется, если задать более 1 аргумента, т.е. {1,2}. При {1} - все ок.
                                        {"test", { .type=_DATA::FLOAT, .children={}, {._float=3.14} } }
                                };
    printf("PRINT:-----\n");
        _CMDDATA::iterator _it, _itEnd;
        for(_it=d2.begin(); _it!=(_itEnd=d2.end()); ++_it)
        {
                printf("%s : %d ", _it->first.c_str(), _it->second.type);
                if(_it->second.type==_DATA::STRING)
                        printf(" STRING %s",_it->second._string.c_str());
                else if(_it->second.type==_DATA::FLOAT)
                        printf(" FLOAT %.6f", _it->second._float);
                else if(_it->second.type==_DATA::BOOL)
                        printf(" BOOL %d", _it->second._bool);
                else if(_it->second.type==_DATA::INTARR)
                {
                        printf(" INTARR(%d) ", _it->second._intarr.size());
                        for(int i = 0; i < _it->second._intarr.size(); i++)
                                printf(" [%d]=%d",i,_it->second._intarr[i]);
                        printf("\n");
                }
                printf("\n");
        }

    printf("DONE!\n");
    return 0;
}


Проблема инициализации сложной структуры данных в std::map, когда задается {._intarr={1,2} } — компилятору не нравится такая инициализация, а если задать {._intarr={1} }, то все ок. Вопрос: головоломку решить вообще реально — инициализация ТОЛЬКО через {} ИМЕННО такой структуры данных (struct{..union{}}) в std::map ?
Какой формы конструктор должен быть, чтобы компилятор проглотил это с {._intarr={1,2} }? Пробовал разные конструкторы, но что-то пока не осилил...

Или это очередной косяк компилятора (как с патчем, описанным выше, без которого в принципе нельзя производить инициализацию union в struct чз {}) ?

P.S. компилировать надо с -D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_C99 -std=C++11 (можно с C++14|17).
Отредактировано 12.12.2019 14:50 lolovo . Предыдущая версия . Еще …
Отредактировано 12.12.2019 14:45 lolovo . Предыдущая версия .
Re: Инициализация чз {} сложной структуры можно или нет?
От: удусекшл  
Дата: 12.12.19 14:45
Оценка:
Здравствуйте, lolovo, Вы писали:

L>Необходима инициализация сложной структуры данных через {}, чтобы было красиво и удобно, без дробления инициализации (т.е. по частям — не надо)... Голову уже сломал над тем, что не так .


У тебя не просто через {}, у тебя с указанием имен полей — это designated initiation. Она вроде не позволяет во вложенность
Re: Инициализация чз {} сложной структуры можно или нет?
От: lolovo  
Дата: 12.12.19 15:19
Оценка:
Все, тема закрыта... добил таки.. если кому интересно, то решение — {"intarr", {_DATA::INTARR,{}, _UVAR{._intarr={1,2}} } }
Отредактировано 12.12.2019 15:19 lolovo . Предыдущая версия .
Re: Инициализация чз {} сложной структуры можно или нет?
От: Muxa  
Дата: 13.12.19 12:19
Оценка:
у тебя определение юниона в структуре скопировано. это норм?
кстати, вот так хранить сложные типы std::string, std::vector в юнионе так просто нельзя.
их деструктор автоматом не вызывается, нужно ручками из деструктора _DATA проверять тип, и вызывать нужный деструктор.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.