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

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

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: чтение и запись битовых структур данных  (Прочитано 21231 раз)
juvf
Программист
*****
Offline Offline

Сообщений: 570


Просмотр профиля
« Ответ #30 : Апрель 28, 2021, 06:43 »

Цитировать
0 или -1?
ответом будет:
Код:
untitled 2:4:11: error: initializing multiple members of union
    float f{0};
          ^
untitled 2:3:9: note: previous initialization is here
    int i{0};
        ^
1 error generated.
Веселый
пффф.... вопрос - что вернёт функция? Функция вернёт 0. А ваша ошибка компиляции из-за инициализации юниона, а не из-за использования. К использованию иниона отношения не имеет... ещё пропустите в примере символ ";" и на основании ошибки компиляции отправте юнион в топку. 

union U
{
    int i{0};
    float f;
};
Тут нет ошибки.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #31 : Апрель 28, 2021, 07:21 »

На эту тему писал свой велик. Продукт проприетарный, поэтому пока опишу только сами подходы.

Реализовывалась работа со структурами специфичного формата данных http://www.eurocontrol.int/services/asterix
Формат данных описывается в параметрическом виде, например, xml

Код
XML
   <DataItem id="020">
       <DataItemName>Target Report Descriptor</DataItemName>
       <DataItemDefinition>Type and characteristics of the radar data as transmitted by a radar station.</DataItemDefinition>
       <DataItemFormat desc="Variable length Data Item comprising a first part of oneoctet, followed by one-octet extents as necessary.">
           <Variable>
               <Fixed length="1">
                   <Bits bit="8">
                       <BitsShortName>TYP</BitsShortName>
                       <BitsValue val="0">Plot</BitsValue>
                       <BitsValue val="1">Track</BitsValue>
                   </Bits>
                   <Bits bit="7">
                       <BitsShortName>SIM</BitsShortName>
                       <BitsValue val="0">Actual plot or track</BitsValue>
                       <BitsValue val="1">Simulated plot or track</BitsValue>
                   </Bits>
                   <Bits from="6" to="5">
                       <BitsShortName>SSRPSR</BitsShortName>
                       <BitsValue val="0">No detection</BitsValue>
                       <BitsValue val="1">Sole primary detection</BitsValue>
                       <BitsValue val="2">Sole secondary detection</BitsValue>
                       <BitsValue val="3">Combined primary and secondary detection</BitsValue>
                   </Bits>
                   <Bits bit="4">
                       <BitsShortName>ANT</BitsShortName>
                       <BitsValue val="0">Target report from antenna 1</BitsValue>
                       <BitsValue val="1">Target report from antenna 2</BitsValue>
                   </Bits>
                   <Bits bit="3">
                       <BitsShortName>SPI</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Special Position Identification</BitsValue>
                   </Bits>
                   <Bits bit="2">
                       <BitsShortName>RAB</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Plot or track from a fixed transponder</BitsValue>
                   </Bits>
                   <Bits bit="1" fx="1">
                       <BitsShortName>FX</BitsShortName>
                       <BitsValue val="0">End of Data Item</BitsValue>
                       <BitsValue val="1">Extension into first extent</BitsValue>
                   </Bits>
               </Fixed>
               <Fixed length="1">
                   <Bits bit="8">
                       <BitsShortName>TST</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Test target indicator</BitsValue>
                   </Bits>
                   <Bits from="7" to="6">
                       <BitsShortName>DS1DS2</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Unlawful interference (code 7500)</BitsValue>
                       <BitsValue val="2">Radio-communication failure (code 7600)</BitsValue>
                       <BitsValue val="3">Emergency (code 7700)</BitsValue>
                   </Bits>
                   <Bits bit="5">
                       <BitsShortName>ME</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Military emergency</BitsValue>
                   </Bits>
                   <Bits bit="4">
                       <BitsShortName>MI</BitsShortName>
                       <BitsValue val="0">Default</BitsValue>
                       <BitsValue val="1">Military identification</BitsValue>
                   </Bits>
                   <Bits from="3" to="2">
                       <BitsShortName>spare</BitsShortName>
                       <BitsName>spare bits set to 0</BitsName>
                       <BitsConst>0</BitsConst>
                   </Bits>
                   <Bits bit="1" fx="1">
                       <BitsShortName>FX</BitsShortName>
                       <BitsValue val="0">End of Data Item</BitsValue>
                       <BitsValue val="1">Extension into next extent</BitsValue>
                   </Bits>
               </Fixed>
           </Variable>
       </DataItemFormat>
   </DataItem>
 
   <DataItem id="040">
       <DataItemName>Measured Position in Polar Coordinates</DataItemName>
       <DataItemDefinition>Measured position of an aircraft in local polar coordinates.</DataItemDefinition>
       <DataItemFormat desc="Four-octet fixed length Data Item.">
           <Fixed length="4">
               <Bits from="32" to="17">
                   <BitsShortName>RHO</BitsShortName>
                   <BitsUnit max="512" scale="0.0078125">NM</BitsUnit>
               </Bits>
               <Bits from="16" to="1">
                   <BitsShortName>THETA</BitsShortName>
                   <BitsUnit scale="0.0054931640625">deg</BitsUnit>
               </Bits>
           </Fixed>
       </DataItemFormat>            
   </DataItem>
 
 

Для этого файла пишется парсер, который формирует структуры с описанием формата данных.

Сами данные представляются в виде последовательности байт, которая обобщена между полями структуры. Поле структуры - это, собственно, ссылка на описание формата данных и на место размещения этих данных в памяти.

Если требуется работать с динамически изменяющимися структурами, то доступ к полям в runtime осуществляется по имени примерно так

Код
C++ (Qt)
record.item( "040" ).field( "RHO" );
 

Если состав структуры известен на этапе компиляции, то по формату xml можно сгенерировать исходники, как предлагал Old или так

Код
C++ (Qt)
 
struct Record
{
   Bytes m_bytes;
 
   // BitField< Byte number,  First bit, Last bit >
   BitField<0, 0, 1> flag;
   BitField<0, 1, 5> mode;
   BitField<0, 5, 14> address;
 
   Record () : flag( m_bytes ), mode( m_bytes ), address( m_bytes ) {}
};
 

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

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Апрель 28, 2021, 10:37 »

необязательно разбирать шаблоны сверхразума внутри библиотеки, если она решает требуемую задачу Улыбающийся
Это довольно скользкое место Улыбающийся Если либа достаточно представительна, авторитетна - то да, можно просто "полагаться". А иначе...

Но главное не это. Не скрою, начало статьи (пример: печать любой, произвольной структуры) впечатляет. Но если немного поразмыслить, то применимость этого - ну, мягко говоря, невелика. Обычно десериализация выглядит так
Код
C++ (Qt)
void A::Read( Stream & strem )
{
 int version = stream.ReadInt();
 
 m_A = stream.ReadInt();
 m_B = stream.ReadInt();
 
 if (version > 1) {
  ...
 
Т.е. заливка из потока - вовсе не "однообразный цикл" по членам. Находятся какие-то подробности которые в общий механизм не ложатся. Пусть их не так уж много, но без них не обойтись. Именно эта "соломинка" часто ломает спину темплейтовскому верблюду  Улыбающийся

Код
C++ (Qt)
 
struct Record
{
   Bytes m_bytes;
 
   // BitField< Byte number,  First bit, Last bit >
   BitField<0, 0, 1> flag;
   BitField<0, 1, 5> mode;
   BitField<0, 5, 14> address;
 
   Record () : flag( m_bytes ), mode( m_bytes ), address( m_bytes ) {}
};
 
Это оправдано если есть такая задача Улыбающийся А делать так только для I/O - явный перебор
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #33 : Апрель 29, 2021, 13:35 »

А давайте попробуем придумать, как удобно можно описывать и использовать такие битовые структуры.
Вот один из возможных вариантов, так сказать для затравки (здесь пока все размеры полей задаются при компиляции):
Код
C++ (Qt)
 struct record
 {
   bit_field<1> flag;
   bit_field<4> mode;
   bit_field<9> address;
 
   bit_array pack() const
   {
     return ::pack( flag, mode, address );
   }
 
   static record  unpack( const bit_array &src )
   {
     record result;
     ::unpack( src, result.flag, result.mode, result.address );
     return result;
   }
 };
 
примерно так и представляется. но хотелось бы избавиться от необходимости явного перечисления полей (пока берем идеальный вариант, где нет никаких записей кусками по условиям, хотя их тоже можно нарезать на более мелкие структуры).

вариант 1 (был выше):
Код:
for field in mystruct.orderedFields
  stream.write(field.size, field.value);
где orderedFields — массив ссылок/указателей на необходимые поля.

вариант 2: заставить кого-то типа Boost.pfr или Boost.Hana (в последней пока ничего не понял из просмотра документации Улыбающийся ) сформировать порядок полей из описания структур в момент компиляции.
На эту тему писал свой велик. Продукт проприетарный, поэтому пока опишу только сами подходы.
спасибо. по сути, описываем структуру во внешнем файле и генерируем для нее парсер и С++ структуры данных. насколько я понимаю, генератор не содержит ни одного зашитого поля, все читается из внешнего файла — вполне хороший способ! хоть и немного громоздкий Улыбающийся

но если удастся описать структуру полностью в рамках С++, то и кодогенератор не понадобится.
Т.е. заливка из потока - вовсе не "однообразный цикл" по членам. Находятся какие-то подробности которые в общий механизм не ложатся. Пусть их не так уж много, но без них не обойтись. Именно эта "соломинка" часто ломает спину темплейтовскому верблюду  Улыбающийся
так можно ж комбинировать: «магические шаблоны» делают свою работу, нестандартные вещи дописать руками.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #34 : Апрель 29, 2021, 15:12 »

вариант 1 (был выше):
Код:
for field in mystruct.orderedFields
  stream.write(field.size, field.value);
где orderedFields — массив ссылок/указателей на необходимые поля.

Наверное такое проще всего реализовать через базовый класс для структур:
Код
C++ (Qt)
class bit_field_base;
 
class bit_record
{
public:
 void reg_field( bit_field_base *field ) { assert( field ); m_orderedFields.push_back( field ); }
 
private:
 std::list<bit_field_base*>  m_orderedFields;
};
 
class bit_field_base
{
public:
 bit_field_base( bit_record &record ) { record.reg_field( this ); }
}
 
 
// =================================================
 
class DataRecord : public bit_record
{
public:
 DataRecord() : m_fld1( *this ), m_fld2( *this ), m_fld3( *this ) {}
 
private:
 bit_field<1> m_fld1;
 bit_field<2> m_fld2;
 bit_field<3> m_fld3;
};
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #35 : Апрель 29, 2021, 16:24 »

но хотелось бы избавиться от необходимости явного перечисления полей
..
по сути, описываем структуру во внешнем файле и генерируем для нее парсер и С++ структуры данных.
..
Такие планы должны иметь более достойные цели чем "битовое чтение/запись".
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #36 : Май 05, 2021, 13:58 »

написал парсер с помощью boost.pfr, пока все выглядит отлично Улыбающийся

«библиотечный» код:
Код
C++ (Qt)
using BitFieldSizeType = uint8_t;
 
template<typename T>
T parseNumber(gsl::span<uint8_t> const& sp, uint64_t& offset, BitFieldSizeType size)
{
 /*
 auto value = bitpacker::extract<T>(sp, offset, size);
 offset += size;
 return value;
 */

 return readBits(size, sp.data(), &offset); // own impl
}
 
template<BitFieldSizeType Bits>
struct BitField
{
 static constexpr auto size = Bits;
 
 std::conditional_t<size == 1, bool,
   std::conditional_t<size <= 8, uint8_t,
     std::conditional_t<size <= 16, uint16_t,
       std::conditional_t<size <= 32, uint32_t, uint64_t>
     >
   >
 > v;
 
 BitField()
 {
   static_assert(size <= 64);
 }
 
 auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset)
 {
   v = parseNumber<decltype(v)>(sp, offset, size);
   return v;
 }
 
  operator auto() const { return v; }
};
 
template<std::size_t Size, BitFieldSizeType Bits>
struct BitArray
{
 std::array<BitField<Bits>, Size> arr;
 
 auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset)
 {
   for (auto& el : arr)
     el.parse(sp, offset);
   return arr;
 }
};
 
// helper types
using BitFieldBool1 = BitField<1>;
 
template<std::size_t Size, BitFieldSizeType Bits = 8>
using BitString = BitArray<Size, Bits>;

парсер:
Код
C++ (Qt)
// helper types
struct NarrowString
{
 std::string string;
 uint8_t maxCharacters;
 
 NarrowString(uint8_t maxCharacters_) : maxCharacters{maxCharacters_}
 {
   assert(maxCharacters > 0);
   string.reserve(maxCharacters - 1);
 }
 
 auto parse(gsl::span<uint8_t> const& sp, uint64_t& offset)
 {
   for (decltype(maxCharacters) j = 0; j < maxCharacters; ++j)
   {
     auto c = BitField<7>{}.parse(sp, offset);
     if (c == 0)
       break;
     string += c;
   }
   return string;
 }
 
 operator auto() const { return string; }
};
 
template<BitFieldSizeType N>
struct ConditionalBitField
{
 BitField<N> _value;
 std::optional<bool> condition;
 
 ConditionalBitField(decltype(condition) condition_ = std::nullopt) : condition{condition_} {}
 
 std::optional<decltype(_value.v)> parse(gsl::span<uint8_t> const& sp, uint64_t& offset)
 {
   bool shouldReadField = condition ? *condition : BitFieldBool1{}.parse(sp, offset);
   if (!shouldReadField)
     return std::nullopt;
   return _value.parse(sp, offset);
 }
};
 
 
// bit structs
struct BasicBitItem
{
 BitField<16> header;
 BitFieldBool1 isQuest;
 BitField<3> _1;
 BitFieldBool1 isIdentified;
 BitField<5+1> _2;
 BitFieldBool1 isSocketed;
 BitField<2+1+1> _3;
 BitFieldBool1 isEar;
 BitFieldBool1 isStarter;
 BitField<2+1> _4;
 BitFieldBool1 isSimple;
 BitFieldBool1 isEthereal;
 BitFieldBool1 _5;
 BitFieldBool1 isPersonalized;
 BitFieldBool1 _6;
 BitFieldBool1 isRW;
 BitField<5+8+2> _7;
 BitField<3> location;
 BitField<4> whereEquipped;
 BitField<4> column;
 BitField<4> row;
 BitField<3> storage;
};
 
struct ExtendedBitItem
{
 BitField<3> socketablesNumber;
 BitField<32> guid;
 BitField<7> ilvl;
 BitField<4> quality;
 ConditionalBitField<3> variableGraphics;
 ConditionalBitField<11> autoprefix;
};
 
 
template <typename F>
void parseField(F& field, gsl::span<uint8_t> const& sp, uint64_t& i)
{
 field.parse(sp, i);
}
 
template <typename T>
T parse(gsl::span<uint8_t> const& sp, uint64_t& i)
{
 T t;
 boost::pfr::for_each_field(t, [&sp, &i](auto& f) {
   parseField(f, sp, i);
 });
 return t;
}
 
 
int main()
{
 // read file...
 gsl::span sp{buf, fileSize};
 uint64_t offset = 0;
 auto base = parse<BasicBitItem>(sp, offset);
 if (base.isSimple)
   return 0;
 
 auto extended = parse<ExtendedBitItem>(sp, offset);
 
 auto someField = ConditionalBitField<16>{base.isRW}.parse(sp, offset);
 if (base.isPersonalized)
   auto inscribedName = NarrowString{16}.parse(sp, offset);
 // further conditions...
 
 return 0;
}

далее надо поместить распарсенное куда-то и обобщить парсер для чтения и записи.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Май 05, 2021, 14:29 »

Код:
// bit structs
struct BasicBitItem
{
  BitField<16> header;
  BitFieldBool1 isQuest;
  BitField<3> _1;
  BitFieldBool1 isIdentified;
  BitField<5+1> _2;
...
Ну хорошо, нарисовали какие-то структуры, с которыми разбираться не один день. Мягко говоря, "для чего"? Чтобы автоматом писались/читались биты? Ну это типа "джин, полей этот цветочек". Может есть какие-то еще цели? Или такой код просто "круче выглядит"?  Улыбающийся
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #38 : Май 05, 2021, 15:10 »

просто глядя на такую struct, и человек, и машина (код) сразу понимают суть — по-моему это намного удобнее, чем лезть в код парсера и искать размеры полей. плюс автоматическое определение нужного размера подлежащего типа (будет жрать меньше памяти, чем просто засунуть uint64_t во все поля).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Май 06, 2021, 18:15 »

просто глядя на такую struct, и человек, и машина (код) сразу понимают суть — по-моему это намного удобнее, чем лезть в код парсера и искать размеры полей. плюс автоматическое определение нужного размера подлежащего типа (будет жрать меньше памяти, чем просто засунуть uint64_t во все поля).
Это типа "двигатели на машинки"  ставить, т.е. да, разумно, полезно, но... Не навязываю своего мнения, но достигаемый ф-ционал мне кажется слишком малым чтобы оправдать создание цепочки классов. К тому же является  ли оно "сутью" - довольно спорно. Напр вполне возможно что структуры имеют смысл и без игр с битами. И иметь размеры полей в объявлении = хорошо, но это только для статики.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #40 : Май 07, 2021, 10:26 »

Попробуем усилить вариант что не гадит темплейтами
Код
C++ (Qt)
void A::ReadWrite( CBitStream & stream, TMode mode )
{
 stream.ReadWriteInt(&m_B, 4, mode);    
 ...
}
Что здесь плохо? Ясно эта "4", которую возможно придется мучительно искать. Завести enum'ы получше, но все-таки не гарантируется что для m_B будет нужный, ошибиться нетрудно, этих enum'ов будет неприятно много. И "4" - только для статики. Тогда может так
Код
C++ (Qt)
usiing TBitKey = std::pair<const std::type_info *, size_t>;
 
template<class Owner, class Member>
int GetBitCount( const Owner & owner, const Member & member )
{
// offsetof ?
 char * base = (char *) &owner;
 char * addr = (char *) &member;
 assert(addr >= base);
 assert(adrr <= base + sizeof(base);
 
 auto it = theGlobalBitsMap.find(TBitKey(&std::typeid(Owner), addr - base));
 assert(it != theGlobalBitsMap.end());
 return it->second;
}
 
// usage
void A::ReadWrite( CBitStream & stream, TMode mode )
{
 stream.ReadWriteBits(&m_B, GetBitCount(*this, m_B), mode);    
 ...
}
Чтобы избавиться от тучи enum'ов. Да, мапу придется заполнять из настроек, ну это неизбежно. Да, легко найти "сколько бит для поля" не получится, но можно напечатать всю мапу. И если нужен "авто-слив" (без почленной сериализации) - его легко сделать с мапой
« Последнее редактирование: Май 07, 2021, 11:06 от Igors » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #41 : Май 08, 2021, 12:48 »

для меня ваш код выглядит намного менее понятно, чем темплейты Улыбающийся typeid так и вовсе никогда в жизни не пользовался (щас бегло посмотрел что это и заметил, что специально для ключа словаря придумали std::type_index, потому что на адрес нельзя закладываться). Если он скрыт в оттестированной библиотеке — буду спокойно пользоваться.

и "авто-слив", и печать, через boost.pfr тоже доступны. а заполнить theGlobalBitsMap без создания объекта не получится, я так понял. то есть выглядит как-то так:
Код
C++ (Qt)
A a;
auto t = std::type_index(std::typeid(A));
theGlobalBitsMap[{t, &a.m_B - &a}] = 6;
и тут прямо напрашиваются макросы для улучшения читабельности Улыбающийся

сюда тоже нужен макрос, ибо ошибку копипастой сделать очень легко:
Код
C++ (Qt)
stream.ReadWriteBits(&m_B, GetBitCount(*this, m_B), mode);
хотя может получится скрыть за функцией, принимающей указатель на член, может ее и затемплейтить можно, чтоб не вставлять в каждую нужную структуру.

по-моему получается очень много ненужной ручной работы плюс доступность лишь в рантайме.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #42 : Май 08, 2021, 16:05 »

специально для ключа словаря придумали std::type_index, потому что на адрес нельзя закладываться
Не вижу где написано что адрес может уплыть, но в любом случае type_index смотрится приятнее.

хотя может получится скрыть за функцией, принимающей указатель на член, может ее и затемплейтить можно, чтоб не вставлять в каждую нужную структуру.
Конечно, напр так
Код
C++ (Qt)
template<class Owner, class Member>
void SetBitsCount( const Owner & owner, const Member & member, int bitsCount );

по-моему получается очень много ненужной ручной работы плюс доступность лишь в рантайме.
Ручная работа = регистрации каждого поля что пишется в биты (одна строка SetBitsCount). Выгода (по сравнению с Вашим вариантом) в том что ничего не навязывается. Простой, житейский сюжет

- Жили-были обычные, нормальные структуры, все работало. Но в один прекрасный день возникла необходимость читать/писать в биты. Хорошо ли менять все обычные int и др на BitField<>? Очевидно нет, это "архитектурно неграмотно" т.к. меняем фундаментальные данные в угоду сиюминутной потребности. А если для структур написано достаточно много кода - такая замена уже нереальна.

Да, и поверьте, где разбить коленки об темплейты - всегда найдется Улыбающийся

и "авто-слив", и печать, через boost.pfr тоже доступны.
Прошу показать (можно вкратце), интересно как

а заполнить theGlobalBitsMap без создания объекта не получится,
Может и можно, но лично я не знаю как. Есть какой-то мутный offsetof, но вроде он "не часть стандарта". Собсно нужно "идентифицировать поле"

для меня ваш код выглядит намного менее понятно, чем темплейты  Улыбающийся
Что же такого непонятного я написал?  Улыбающийся
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #43 : Май 08, 2021, 19:25 »

Цитировать
Не вижу где написано что адрес может уплыть
https://en.cppreference.com/w/cpp/language/typeid Notes:
Цитировать
There is no guarantee that the same std::type_info instance will be referred to by all evaluations of the typeid expression on the same type, although std::type_info::hash_code of those type_info objects would be identical, as would be their std::type_index.
Код
C++ (Qt)
const std::type_info& ti1 = typeid(A);
const std::type_info& ti2 = typeid(A);
 
assert(&ti1 == &ti2); // not guaranteed
assert(ti1.hash_code() == ti2.hash_code()); // guaranteed
assert(std::type_index(ti1) == std::type_index(ti2)); // guaranteed

Цитировать
Простой, житейский сюжет
но это не мой сюжет Улыбающийся сырые битовые структуры и те, с которыми удобно работать — разные сущности.
Цитировать
Прошу показать (можно вкратце), интересно как
"авто-слив" в приведенном парсере уже по сути есть:
Код
C++ (Qt)
 boost::pfr::for_each_field(some_struct, [](auto const& f) {
   // делаем с полем f что хотим
   std::cout << f.size;
 });
можно и пользовательский вывод определить (не пробовал): https://www.boost.org/doc/libs/develop/doc/html/boost_pfr/tutorial.html#boost_pfr.tutorial.custom_printing_of_aggregates и следующий раздел

стандартный вывод просто печатает все поля по порядку:
Код
C++ (Qt)
std::cout << boost::pfr::io(some_struct);
Цитировать
Что же такого непонятного я написал?
все эти игры с typeid и указателями на члены, никогда не сталкивался Улыбающийся
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #44 : Май 09, 2021, 09:52 »

Да, верно, спасибо
"авто-слив" в приведенном парсере уже по сути есть:
Код
C++ (Qt)
 boost::pfr::for_each_field(some_struct, [](auto const& f) {
   // делаем с полем f что хотим
   std::cout << f.size;
 });
Ага, вот он, "момент истины". Оказывается дуст умеет "перебирать по полям" как я видел в статейке. А просто так заграбастать эту ф-цию нельзя? Пусть с мапой тоже несложно, но так еще лучше.

Хотя это совсем не означает что нужно искалечить все нормальные члены только для того чтобы иметь битовый размер. Кстати для статики почему бы не задействовать простецкие bitfield (от которых Вы гордо отказались). Напр
Код
C++ (Qt)
union CFlag {
 uint32 m_value;
 struct {
   uint32 m_A : 1;
   uint32 m_B : 2;
   ...
 };
};
И для мапы - только m_value. Это заметно схлопнет число всяких мелких полей. А на понты про union не обращайте внимания, то так, "что-то читал"  Улыбающийся

но это не мой сюжет Улыбающийся сырые битовые структуры и те, с которыми удобно работать — разные сущности.
Ну а зачем иметь/заводить 2 представления данных ? Я бы этого всячески избегал
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


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