Получить размер полей структуры в compile-time
От: A.J. Россия CintaNotes
Дата: 12.11.24 17:04
Оценка:
Нужно для реализации учета занимаемой памяти.

Есть функция classSize, принимающая объект типа S и parameter pack из всех полей S.
Parameter pack нужен, т.к. для каждого поля нужно еще вызвать метод getExtraUsedMemory(field).

Хочется в compile-time проверить, что никакое поле не забыли. Пришла идея сделать compile-time
функцию calcMembersSize, куда передавать тот же список полей, и сравнивать результат с sizeof(S).

Подскажите, можно ли реализовать подсчет размеров полей (вместе с padding) в compile-time?
Функция должна учитывать возможность наличия vtable и полей базовых классов
(поэтому не подходит Boost.PFR, который требует standard layout).

Можно предполагать 20й стандарт. Должно работать под GCC 13. Ок если под другими компиляторами работать не будет!

Сами структуры менять нельзя, в том числе навешивать на них #pragma pack(1).

#include <iostream>

template <typename T, typename... Members>
consteval size_t calcMembersSize(Members&&... members) 
{
    // ?
}

struct B {
    virtual void v() {}
};

struct C {
    virtual void w() {}
};

struct D {
    int j;
};

struct E {};

struct A : B, C, D 
{
    int i;
    double d;
    short s;
    bool b;
    std::string str;
    char c;
};

int main() {  
    A a;    
    // Перечислять можно в любом порядке, но должны быть указаны все поля
    static_assert(calcMembersSize<A>(a.i, a.d, a.s, a.b, a.str, a.c) == sizeof(a));
    static_assert(calcMembersSize<A>(a.str, a.i, a.s, a.b, a.c, a.d) == sizeof(a));
    static_assert(calcMembersSize<A>(a.d, a.i, a.c, a.s, a.str, a.b) == sizeof(a));

    static_assert(calcMembersSize<A>(a.d, a.s, a.c, a.b, a.str) != sizeof(a));
    static_assert(calcMembersSize<A>(a.i, a.s, a.c, a.b, a.str) != sizeof(a));
    static_assert(calcMembersSize<A>(a.i, a.d, a.c, a.b, a.str) != sizeof(a));
    static_assert(calcMembersSize<A>(a.i, a.d, a.s, a.str) != sizeof(a));
    static_assert(calcMembersSize<A>(a.i, a.d, a.s, a.str) != sizeof(a));
}


Заранее спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.