Печать значений всех полей в структуре 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++ не производят метаданные. Так что нет возможности сделать такую ​​вещь.

С 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++ редко, если вообще когда-либо, хранит такие метаданные об объектах.

Другие вопросы по тегам