Печать значений всех полей в структуре C++
Рассмотрим простую структуру:
struct abc
{
int a;
char b;
}
Я получил некоторое значение в переменной, определенной как ее структура, и теперь я хочу напечатать ниже.
*a = [some value]
b = [some character]*
Каков наилучший способ добиться этого для произвольной структуры без необходимости писать функцию dump...(...) для каждой структуры, с которой я сталкиваюсь?
5 ответов
Кажется, вы уже нашли решение, но я немного расширю.
То, к чему ты призываешь, называется Reflection
способность объекта описывать себя.
Большинство языков реализуют отражение благодаря метаданным, например, в python функции и атрибуты объекта хранятся в элементе словаря.
C++ не имеет никакой собственной системы отражения в отличие от C# или Java, которая предотвращает (например) этот вид автоматической печати / сериализации или десериализации.
Тем не менее, C++ имеет очень мощную поддержку метапрограммирования, которая позволяет нам (посредством использования шаблонов) эмулировать отражение (во время компиляции). Обычно это делается с помощью Boost.Fusion, эта библиотека предназначена для перехода от компиляции во время выполнения.
Как показано в примере по вашей ссылке, BOOST_FUSION_ADAPT_STRUCT
макрос позволяет взять стандарт struct
и дать ему необходимый интерфейс, который будет рассматриваться как последовательность Fusion.Sequence.
Другой пример будет использовать Fusion.Vector
или же Fusion.Map
сохранить атрибуты класса и затем открыть эту последовательность для автоматических методов печати / сериализации / десериализации.
Однако у этой системы есть ограничение: метапрограммирование плохо сочетается с ОО-программированием.
struct Base { char a; }; // Adapt
struct Derived: Base { char b; }; // Adapt
void print(Base const& b) { boost::fusion::for_each<Base>(b, Print()); }
будет печатать только член Base
(Вот a
). При использовании полиморфизма необходимо использовать virtual
методы в тот или иной момент:)
Вам нужно "отражение", чтобы сделать это. Отражение не предоставляется изначально в C++ или только для минимальной информации (тип идентификаторы / имена).
Существуют библиотеки (например, CAMP), которые реализуют функции отражения, поэтому, если вы действительно нуждаетесь в отражении, вы должны использовать его.
Компиляторы C++ не производят метаданные. Так что нет возможности сделать такую вещь.
С C++17 (возможно, даже C++14) и некоторыми сумасшедшими русскими взломами - это можно сделать частично. То есть вы можете печатать значения типов по порядку, но не можете получить имена полей.
Соответствующей библиотекой является "magic_get" Антония Полухина. В частности, он предлагает механизм итерации "для каждого поля", который принимает шаблонную лямбду с auto
тип параметра. Пример:
struct simple {
int a;
char b;
short d;
};
simple x {42, 'a', 3};
std::stringstream ss;
boost::pfr::for_each_field(
x,
[&ss](auto&& val) {
ss << val << ' ';
}
);
Ответ перенесен из похожего / дублирующего вопроса - так как здесь никто не упомянул об этом.
Просто сделай это
#include<iostream>
using namespace std;
struct abc
{
int a;
char b;
};
void display(abc myStruct){
cout << "struct abc {"<< endl;
cout << abc.a << endl;
cout << abc.b << endl;
cout << "}" << endl;
}
int main(){
abc myStruct
display(myStruct);
}
отражение требуется только тогда, когда структуры будут определяться пользователем, а не вами, и вы не уверены во внутренней структуре структуры.
Если вы используете C++ в.NET, вы можете использовать System.Reflection, чтобы посмотреть на внутренности вашей структуры. Однако неуправляемый C++ редко, если вообще когда-либо, хранит такие метаданные об объектах.