Дамп объекта в С++, например var_dump() в PHP?
Когда я учился в колледже, я сделал несколько C/С++, но в ближайшем будущем я работал в PHP, и теперь я хочу больше времени уделять изучению C/С++.
В PHP я использовал print_r() или var_dump(), чтобы отображать данные из структур или массивов. У меня есть такая функция по умолчанию в C, чтобы узнать, что у меня есть в структуре или массиве?
Ответы
Ответ 1
В С++ таких функций нет. Вы можете, конечно, написать свои собственные функции Dump(). Причина, по которой такая функция вообще не может быть предоставлена, заключается в том, что процесс компиляции С++ удаляет метаданные объекта, необходимые для структурирования вывода дампа. Конечно, вы можете отображать содержимое структуры в отладчике, где такие метаданные хранятся в отладочной информации.
Кстати, вы спрашиваете о C или С++? Эти два языка совершенно разные, как в функциях, так и в подходах, хотя ни один из них не имеет var_dump() или аналогичного.
Ответ 2
С++ сам по себе не предоставляет что-то вроде var_dump, но с такими библиотеками, как Boost.Fusion и ADAPT_STRUCT и ADAPT_ADT, это легко выполнимо.
В самом деле, как сказано в другом ответе, компилятор С++ не генерирует метаданные, необходимые для создания такого вывода. Однако эти метаданные можно сгенерировать и использовать метапрограммирование нескольких шаблонов для их использования.
Таким образом, я реализовал здесь adapt_struct_printer, который может печатать std:: container, любые классы или структуры, boost:: variant и boost:: tuple.
Новое решение
Теперь вы можете легко сделать следующее:
#include <iostream>
#include <pre/json/to_json.hpp>
struct customer {
std::string name;
size_t money_spent;
std::vector<std::string> interests;
};
BOOST_FUSION_ADAPT_STRUCT(customer,
name,
money_spent,
interests)
...
customer my_customer{
"Mr. Dupond",
1000,
{"sport articles", "food", "tools"}
};
std::cout << pre::json::to_json(my_customer) << std::endl;
Вы можете обратно с этой библиотекой также сделать from_json для заполнения структур из json.
Документация доступна здесь: http://daminetreg.github.io/lib-cpp-pre/html/namespacepre_1_1json.html#a4325d2cdd64a7e321303fd4428f298b9
OLD Response
Единственное требование - вы вызываете BOOST_FUSION_ADAPT_STRUCT/BOOST_FUSION_ADAPT_ADT на своих классах (см. http://www.boost.org/doc/libs/1_57_0/libs/fusion/doc/html/fusion/adapted.html)
Итак, этот пример:
#include <iostream>
#include <swissarmyknife/boost/fusion/adapted_struct_printer.hpp>
#include <boost/fusion/include/define_struct.hpp>
#include <boost/variant.hpp>
#include <boost/tuple/tuple.hpp>
namespace bla {
struct someclass {
int i = 12;
int j = 15;
};
using boost::fusion::detail::operator <<;
}
BOOST_FUSION_ADAPT_STRUCT(bla::someclass,
(int, i)
(int, j)
)
BOOST_FUSION_DEFINE_STRUCT((bla), innerbim,
(std::string, mystring)
)
BOOST_FUSION_DEFINE_STRUCT((bla), bimbim,
(int, boom)
(int, bam)
(bla::innerbim, my_inner_bim)
)
typedef boost::variant<int, double, bla::innerbim> myvariant_t;
typedef boost::tuple<std::string, int, bla::innerbim, myvariant_t> my_tuple_t;
BOOST_FUSION_DEFINE_STRUCT((bla), blabla,
(bla::bimbim, bim)
(int, i)
(int, j)
(std::vector<double>, list)
(std::list<bla::bimbim>, list_of_bimbim)
(my_tuple_t, mytuple)
(myvariant_t, myvariant)
)
int main(int argc, char** argv) {
using namespace swak;
bla::blabla instance{
{22, 12, bla::innerbim{"COOL"} },
23,
43,
{2.00, 39.07, 24.05},
{
{24, 9, bla::innerbim{"FEEL GOOD"} },
{26, 14, bla::innerbim{"SO BAD"} },
},
{"Hey that not an int", 1, bla::innerbim{"hello"}, 12},
bla::innerbim("I'm in the variant")
};
std::cout << instance << std::endl;
bla::someclass otherinstance{};
std::cout << "Other instance : " << otherinstance << std::endl;
return 0;
}
Распечатывает следующее:
{
bim :
{
boom : 22,
bam : 12,
my_inner_bim :
{
mystring : COOL,
}
}
i : 23,
j : 43,
list : [2, 39.07, 24.05],
list_of_bimbim : [
{
boom : 24,
bam : 9,
my_inner_bim :
{
mystring : FEEL GOOD,
}
}
,
{
boom : 26,
bam : 14,
my_inner_bim :
{
mystring : SO BAD,
}
}
],
mytuple :
{
0 (Ss) : Hey that not an int,
1 (i) : 1,
2 (N3bla8innerbimE) :
{
mystring : hello,
}
3 (N5boost7variantIidN3bla8innerbimENS_6detail7variant5void_ES5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_S5_EE) :
{
12}
}
myvariant :
{
{
mystring : I'm in the variant,
}
}
}
Other instance :
{
i : 12,
j : 15,
}
Я улучшаю реализацию, чтобы получить ее в какой-то момент как возможную новую функцию в boost fusion, но она уже используется, как показано на рисунке:
https://github.com/daminetreg/lib-cpp-swissarmyknife/blob/feature/adapted_struct_printer_improved/test/adapted_struct_printer.cpp
Ответ 3
Нет, вам нужно сворачивать свой собственный, используя один из семейств функций вывода cout
или C style printf
для пользовательских структур данных. Аналогично, для массивов (кроме строк в стиле C) вам придется перебирать все элементы и печатать каждый.
Ответ 4
Нет, нет. Например, используйте отладчик, например ddd. Большинство IDE имеют один интегрированный интерфейс.
Ответ 5
Это возможно, но потребовалось бы много работы, если бы были включены символы отладки, и все оптимизации были отключены. Также он будет медленным и, возможно, не очень надежным [* 1].
Все, что может сделать отладчик, может быть реплицировано функцией dump(), которая вызывает точку останова и выведенную из нее информацию.
Некоторые отладчики могут быть автоматизированы, поэтому, возможно, сама функция дампа будет записана в отладчике.
* 1, например. отладчики иногда сбой при работе с некоторыми точками останова. например программа должна будет иметь точку останова и остановить все потоки, прежде чем пытаться сбрасывать данные. например программы, которые должны иметь дело с прерываниями в реальном времени, вероятно, не сработают. например отладчик должен быть достаточно надежным, чтобы иметь дело с множеством точек останова и не вводить другие проблемы.
Ответ 6
В статье Microsoft есть некоторое решение:
вектор:: push_back
https://msdn.microsoft.com/pt-br/library/7fthz5xd.aspx
template <typename T> void print_elem(const T& t) {
cout << "(" << t << ") ";
}
template <typename T> void print_collection(const T& t) {
cout << " " << t.size() << " elements: ";
for (const auto& p : t) {
print_elem(p);
}
cout << endl;
}
и вызов для этого:
cout << "vector data: " << endl;
print_collection(v);