Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Как узнать количество полей в структуре?

#cpp


Как узнать количество полей в структуре?

struct A {
  int a,b; // 2 поля
}

struct B {
  float a,b,c; // 3 поля
}

    


Ответы

Ответ 1



В общем случае это невозможно. В C++23 должны добавить рефлексию, с помощью которой это можно будет делать, но до тех пор придется довольствоваться разными сомнительными хаками. Есть несколько решений для частных случаев: Если у вас все поля в структуре одного типа, и вы знаете, какого именно, то, как предложил @ARHovsepyan, можно поделить размер структуры на размер одного ее члена: int main() { std::cout << sizeof(A) / sizeof(int) << '\n'; std::cout << sizeof(B) / sizeof(float) << '\n'; } Хотя, ЕМНИП, компиляторам разрешается добавлять в структуры сколько угодно неиспользуемых байт (padding) между и после полей, чтобы расположить их в памяти определенным образом (из-за чего этот трюк перестал бы работать), я еще не видел ни одного компилятора, который действительно делал бы это для структур с полями одного типа. Есть еще один вариант, более универсальный. Если вы не создали для вашей структуры ни одного конструктора, и в структуре нет полей-массивов, то можно сделать вот что: #include #include #include #include struct stub { template operator T() const; }; template using detect_brace_constructible = decltype(T{std::declval

()...}); template constexpr bool constructible_with_stubs(std::index_sequence) { return std::experimental::is_detected_v< detect_brace_constructible, T, std::enable_if_t<1 || I, stub>... >; } template constexpr int field_count_impl(std::index_sequence) { int ret = -1; ((void(ret = I), constructible_with_stubs(std::make_index_sequence{})) && ...); return ret-1; } template inline constexpr int field_count = field_count_impl(std::make_index_sequence{}); struct A { int a,b; }; struct B { float a,b,c; }; int main() { std::cout << field_count << '\n'; // 2 std::cout << field_count << '\n'; // 3 } Этот шаблон последовательно пробует конструировать структуру с возрастающим количеством аргументов: A{} A{stub{}} A{stub{}, stub{}} A{stub{}, stub{}, stub{}} ... Где stub{} - это заглушка, которая может быть преобразована в любой нужный тип. Такое конструирование будет успешно, пока заглушек столько же, сколько полей в структуре, или меньше. Если заглушек будет больше - будет ошибка. Мы эту ошибку обнаруживаем с помощью SFINAE и возвращаем число заглушек, при котором ошибки не было. Но если в структуре есть массив, то такой шаблон ошибочно посчитает каждый элемент массива за отдельное поле структуры.

Ответ 2



В добавление к существующему ответу: есть библиотека Precise and Flat Reflection, в которой реализован требуемый функционал. Там же можно посмотреть как всё сделано, если интересна реализация.

Комментариев нет:

Отправить комментарий