Russian Qt Forum
Ноябрь 22, 2024, 18:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: MetaData (Lite)  (Прочитано 4781 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Август 30, 2016, 09:04 »

Добрый день

Набегают новые фичи, к базовой структуре постоянно добавляются новые члены данных нужные для какого-то конкретного случая. Нормально сделать мапу чтобы по ключу добавлять/брать такие данные (вместо того чтобы менять структуру всякий раз). По смыслу QVariantMap подходит, но связываться с обильным QVariant не хочется, да и в данных файлах Qt нет, тащить его из-за такой мелочи не резон. Тогда как иначе? В принципе пока устраивает даже
Код
C++ (Qt)
std::map<int, void *>
Т.к. данные POD. Но уж слишком вызывающе - С приведения, удаление void. Как бы это сделать аккуратнее и чтобы было скромно, компактно?

Спасибо
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Август 30, 2016, 10:19 »

сделать свой union ?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #2 : Август 30, 2016, 10:42 »

Лучше сделать по типу boost::any, там кода не так уж и много, зато не торчит никакой void *

Если кратко, то заводим AbstractHolder, для каждого типа от него порождаем Holder< _Type >. Строим Variant/Any поверх указателя на Holder.

Простейший случай выглядит как-то так

Код
C++ (Qt)
   struct AbstractHolder;
   std::shared_ptr< AbstractHolder > SharedHolder;
 
   struct AbstractHolder
   {
   public:
       virtual ~AbstractHolder () {}
       virtual const char * type () const = 0;
       virtual SharedHolder clone () const = 0;
   };
 
   template < typename _Value >
   struct Holder
       : public AbstractHolder
   {
   public:
       typedef Holder< _Value > ThisType;
 
   public:
       _Value m_value;
 
   public:
       Holder () : m_value() {}
       template < typename _Type >
       Holder ( const _Type & value ): m_value( value ) {}
       virtual const char * type () const ( typeid( _Type >().name(); }
       virtual SharedHolder clone () const { return SharedHolder( new ThisType( m_value ); }
   };
 
   class Variant
   {
       SharedHolder m_holder;
 
   public:
       Variant () : m_holder() {}
       Variant ( const Variant & other ) : m_holder() { *this = other; }
       Variant & operator = ( const Variant & other ) { m_holder = other.m_holder ? other.m_holder->clone() : SharedHolder(); }
 
       template < typename _Type >
       bool isA () const { return m_holder ? typeid( _Type ).name() == m_holder.type() : false; }
       template < typename _Type >
       const _Type value () const { return isA< _Type >() ? static_cast< const Holder< _Type > * >( &*m_holder )->m_value : _Type() }
       template < typename _Type >
       static Variant fromValue ( const _Type & value ) { Variant result; result.m_holder = SharedHolder( new Holder< _Type >( value ) ); }
   };
 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #3 : Август 30, 2016, 10:47 »

Лучше сделать по типу boost::any, там кода не так уж и много, зато не торчит никакой void *
Да уже даже есть готовое решение, горячО обсужденное. Улыбающийся
http://www.prog.org.ru/topic_28407_0.html
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #4 : Август 30, 2016, 22:51 »

Добрый день

Набегают новые фичи, к базовой структуре постоянно добавляются новые члены данных нужные для какого-то конкретного случая. Нормально сделать мапу чтобы по ключу добавлять/брать такие данные (вместо того чтобы менять структуру всякий раз). По смыслу QVariantMap подходит, но связываться с обильным QVariant не хочется, да и в данных файлах Qt нет, тащить его из-за такой мелочи не резон. Тогда как иначе? В принципе пока устраивает даже
Код
C++ (Qt)
std::map<int, void *>
Т.к. данные POD. Но уж слишком вызывающе - С приведения, удаление void. Как бы это сделать аккуратнее и чтобы было скромно, компактно?

Спасибо


сначала - void*

затем, если будет актуально, время и желание - Arg.
это - "умный void*"
c возможностью проверки типизации и квалификатора const времени выполнения.

суть такая: в зависимости от опций компиляции Arg сворачивается в тот же void*,
или валидирует assert`ами.
или валидирует exception`ами.

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Август 31, 2016, 15:20 »

Если кратко, то заводим AbstractHolder, для каждого типа от него порождаем Holder< _Type >. Строим Variant/Any поверх указателя на Holder.

Простейший случай выглядит как-то так
Я пошел др путем (аттач)  Улыбающийся, но получилось похоже - тоже holder, тоже выртуальная база  и наследуемый от нее темплейтник. Да, эта конструкция делает все что требуется и неплохо расширяема, но колоссальный минус - всякое отсутствие желанной простоты  Плачущий Вот если таких классов мало, они хорошо известны, "узаконены" в проекте и под рукой online help - тогда да, они полезны. А иначе они не стоят того чтобы с ними разбираться.

сделать свой union ?
И в деструкторе свитчеваться?  И на get/set проверять тип сохраненный явно? Не, ну так я давно умею Улыбающийся

затем, если будет актуально, время и желание - Arg.
это - "умный void*"
c возможностью проверки типизации и квалификатора const времени выполнения.
Цитировать
Будете у нас на Колыме...
Нет уж!! Лучше Вы у нам!
Улыбающийся
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Август 31, 2016, 15:43 »

union позволяет избежать дополнительных аллокаций памяти и проверок рантайма (что бьёт по производительности). А насчет свитчей в деструкторе "моя не поняла". Достаточно юниона + одного флага, который хранит тип данных (я ж так понял, что все типы - должны быть чисто POD?)
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Сентябрь 01, 2016, 06:43 »

union позволяет избежать дополнительных аллокаций памяти и проверок рантайма (что бьёт по производительности). А насчет свитчей в деструкторе "моя не поняла". Достаточно юниона + одного флага, который хранит тип данных (я ж так понял, что все типы - должны быть чисто POD?)
Пока POD, дальше хз
Код
C++ (Qt)
struct MyU {
int mTypeID;
union {
  MyStruct1 s1;
  MyStruct2 s2;
  ...
};
};
Вот появится MyStruct3 всего лишь имеющий конструктор - и все, приплыли. Поэтому придется так
Код
C++ (Qt)
struct MyU {
int mTypeID;
union {
  MyStruct1 * s1;
  MyStruct2 * s2;
  ...
};
};
Но тогда вылазят саитчи. В обоих случаях неприятно что все хедеры (где описаны MyStruct xxx) должны присутствовать, MyU "обо всех знает", а это хреново.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.413 секунд. Запросов: 23.