I have below struct
struct abc
{
int a1;
char c1;
float f1;
int a2;
char c2;
float f2;
.
.
.
int aa1000;
char cc1000;
float ff1000;
} ;
all member of struct has different names. here for the sake of typing I have just denoted them as a1, a2 , c1, c2 and so on ... .
so array can't be created for members.
This struct is having more than 1 thousand members.
I want to print all of them in a single go for debugging purposes.
Stuct is very large otherwise a simple print function could have been written which will print each and every member.
But here, there many struct of this kind having more than thousand members and writing print function for each of them is not feasible.
Is there any way to dump/print all member of struct ?
Refactor direction :
#include <array>
#include <iostream>
//-----------------------------------------------------------------------------
struct xyz
{
int a{0};
char c{'x'};
float f{};
};
struct abc
{
std::array<xyz, 1000> records;
};
//-----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, const xyz& record)
{
os << "a = " << record.a << ", c = " << record.c << ", f = " << record.f << "\n";
return os;
}
std::ostream& operator<<(std::ostream& os, const abc& data)
{
std::size_t n{ 0 };
for (const auto& record : data.records)
{
os << "record[" << n++ << "] : ";
os << record;
}
return os;
}
//-----------------------------------------------------------------------------
int main()
{
abc data;
// data.x1 -> abc.x[0] etc...
// data.x2 -> abc.x[1] etc...
// data.x3 -> abc.x[2] etc...
std::cout << data;
}
Related
I have a class Twhich has a map of string class T
For convinience, I would like to print the content in the class in an organized manner with tabulations.
As an example, I have:
#include <iostream>
#include <map>
#include <string>
class test;
typedef std::map<std::string, std::string> sMap;
typedef std::map<std::string, test> testMap;
class test {
public:
sMap map1;
testMap map2;
};
std::ostream& operator<<(std::ostream& os, const sMap& smap) {
for(const auto& s_smap : smap) {
os << s_smap.first
<< "\t"
<< s_smap.second
<< "\n";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const test& t) {
os << t.map1
<< "\n";
for (const auto& s_map : t.map2) {
os << s_map.first
<< "\t"
<< s_map.second
<< std::endl;
}
return os;
}
int main() {
sMap myMap;
myMap["a"] = "b";
test obj;
obj.map1 = myMap;
test obj2;
obj2.map2.insert({"one", obj});
obj2.map2["one"].map2.insert({"two", obj});
obj2.map2["one"].map2["two"].map2.insert({"three", obj});
obj2.map2["one"].map2["two"].map2["three"].map2.insert({"four", obj});
std::cout << obj2 << std::endl;
return 0;
}
I would like the output to be:
one a b
two a b
three a b
four a b
How can the operator<< be overloaded to achieve this?
Doing this means you need to pass along extra information. You could create a printMap kind of fucntion that takes an indentation level as an argument, but you've said you want to achieve this by overloading operator<< so you can't pass that along unless you wrap your test objects in another class/struct that does carry that info.
That might look something like the below, which outputs:
% ./a.out
a b
a b
a b
a b
Tweaking this is left as an exercise for the OP.
#include <iostream>
#include <map>
#include <string>
struct test;
using sMap = std::map<std::string, std::string>;
using testMap = std::map<std::string, test>;
struct test {
sMap map1;
testMap map2;
};
struct indent {
const test &ref;
int indentLevel;
indent(const test &ref, int indentLevel=0)
: ref(ref), indentLevel(indentLevel)
{ }
};
std::ostream& operator<<(std::ostream& os, const indent &i) {
int j = i.indentLevel;
for (const auto &[f, s] : i.ref.map1) {
for (int k = 0; k < j; k++) os << "\t";
os << f << "\t" << s << "\n";
}
for (const auto &[f, s] : i.ref.map2) {
os << indent(s, j + 1);
}
return os;
}
std::ostream& operator<<(std::ostream& os, const sMap& smap) {
for (const auto &[f, s] : smap) {
os << f << "\t" << s << "\n";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const test& t) {
os << t.map1
<< "\n";
for (const auto& s_map : t.map2) {
os << s_map.first
<< "\t"
<< s_map.second
<< std::endl;
}
return os;
}
int main() {
sMap myMap;
myMap["a"] = "b";
test obj;
obj.map1 = myMap;
test obj2;
obj2.map2.insert({"one", obj});
obj2.map2["one"].map2.insert({"two", obj});
obj2.map2["one"].map2["two"].map2.insert({"three", obj});
obj2.map2["one"].map2["two"].map2["three"].map2.insert({"four", obj});
std::cout << indent(obj2) << std::endl;
return 0;
}
Some aspects of this case incorporate post-C++11 features like structured bindings. If a newer standard cannot be used, these techniques can be converted to C++11 friendly constructs.
Need some idea how to convert struct (might be also nested) to line of strings where each string is the number of the struct according to the order.
I hope i clear enough.
For example:
struct MyStruct
{
int a;
float b;
};
struct External
{
double c;
MyStruct d;
};
void main()
{
External x;
x.c = 2.345;
x.d.a = 12;
x.d.b = 3.8f;
std:string res = convert_to_string (&x);
cout << res;
// Expected print result:
// "2.345, 12, 3.8"
}
The struct can be very long, so the solution of sorts of itoa(dtoa) or sprintf for each field is possible, but very long and needs code update for every struct change.
Probably some kind of struct run-time or precompile parsing and serialization is needed here.
Ideas ?
What about this? C++ to the rescue :)
#include <iostream>
struct MyStruct {
int a;
float b;
friend std::ostream& operator<<(std::ostream& os, const MyStruct& ms) {
std::cout << std::to_string(ms.a) << " " << std::to_string(ms.b);
return os;
}
};
struct External {
double c;
MyStruct d;
friend std::ostream& operator<<(std::ostream& os, const External& e) {
std::cout << std::to_string(e.c) << " " << e.d;
return os;
}
};
int main() {
External x;
x.c = 2.345;
x.d.a = 12;
x.d.b = 3.8f;
std::cout << x << std::endl;
// Expected print result:
// "2.345, 12, 3.8"
}
Or if you really want a string:
#include <iostream>
struct MyStruct {
int a;
float b;
std::string to_string() const {
std::string str = std::to_string(this->a);
str += " ";
str += std::to_string(this->b);
return str;
}
};
struct External {
double c;
MyStruct d;
std::string to_string() const {
std::string str = std::to_string(this->c);
str += " ";
str += this->d.to_string();
return str;
}
};
int main() {
External x;
x.c = 2.345;
x.d.a = 12;
x.d.b = 3.8f;
std::cout << x.to_string() << std::endl;
// Expected print result:
// "2.345, 12, 3.8"
}
When I say "attribute", I mean something along the lines of std:array<int, 5> arr. The 5 is an attribute of the array.
Here's a motivating example: suppose I want to create a number or string that contains formatting information. So I might like to be able to write Double<7,2> foo, meaning that I want foo to be a double, and when I print it, it is to have width 7, and precision 2. I can make assignments in the usual way:
foo = 42;
double bar = foo;
Is there a way to do this?
You might be asking why I want to do it this way. Why not, for example, define a class that takes width and precision in its constructor? The answer is that I don't think you can use them in structures. For example, I want to be able to do something like:
struct Account {
std::string description;
Double<7, 2> amount;
Double<7, 2> balance;
Double<9, 3> percent;
};
You can write your own wrapper class with Non-type template parameters and double implicit conversion. The advantage is that the size of such class remains the same.
#include <iostream>
template<std::streamsize WIDTH, std::streamsize PRECISION>
struct DoubleEx
{
double value;
DoubleEx(double fValue) : value(fValue) {}
operator double() const { return value; }
friend std::ostream& operator << (std::ostream& stream, const DoubleEx &val)
{
stream.width(WIDTH);
auto oldPrecision = stream.precision();
stream.precision(PRECISION);
stream << val.value;
stream.precision(oldPrecision);
return stream;
}
};
int main()
{
DoubleEx<15, 8> num1 = 123.45678;
double num2 = num1;
auto num3 = num1;
std::cout << "num1 = " << num1 << " size=" << sizeof(num1) << std::endl;
std::cout << "num2 = " << num2 << " size=" << sizeof(num2) << std::endl;
std::cout << "num3 = " << num3 << " size=" << sizeof(num3) << std::endl;
}
Output:
num1 = 123.45678 size=8
num2 = 123.457 size=8
num3 = 123.45678 size=8
Not sure I got what you mean, but maybe mixins can help you.
As a minimal, working example:
#include <cstddef>
#include <string>
template<std::size_t N, std::size_t M>
struct Double {
operator double() { return N*M; }
};
struct Description {
std::string description;
};
template<typename ...T>
struct Mock: T... { };
using Account = Mock<Double<7, 2>, Description>;
int main() {
Account account;
account.description = "foo";
double d = account;
}
I declare a simple struct together with default constructor, copy constructor, assignment operator, and destructor. However, the struct does not work as a value type for std::map.
Here is the code:
#include <string.h>
#include <iostream>
#include <string>
#include <map>
class Foo;
std::ostream & operator<<(std::ostream & os, const Foo & v);
typedef unsigned char BYTE;
struct Foo {
char type_; // char to label type
size_t num_; // number of elem, useful if array
size_t total_; // total memory
BYTE * data_; // content of memory
Foo(const char * t) : type_('c'), num_(strlen(t)+1), total_(strlen(t)+1), data_(NULL) {
data_ = new BYTE[total_];
memcpy(data_, t, total_-1);
((char *)data_)[total_-1] = '\0';
}
Foo() : type_(), num_(), total_(), data_(NULL) {}
Foo(const Foo& rhs) : type_(rhs.type_), num_(rhs.num_), total_(rhs.total_), data_(NULL) {
if (total_) {
data_ = new BYTE[total_];
memcpy((char *)data_, (const char *)&rhs.data_, total_);
}
}
Foo & operator=(const Foo& rhs) {
if (&rhs != this) {
releaseData();
type_ = rhs.type_;
num_ = rhs.num_;
total_ = rhs.total_;
data_ = new BYTE[total_];
memcpy(data_, &rhs.data_, total_);
}
return *this;
}
~Foo() {
releaseData();
}
private:
void releaseData() {
delete [] data_; data_ = NULL;
}
};
inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
os << "(type: " << v.type_ << ", num: " << v.num_ << ", total: " << v.total_ << ", data: " << (const char *)v.data_ << ", data addr: " << (void *)v.data_ << ")";
return os;
}
int main() {
Foo c("/home/data/");
std::map<std::string, Foo> store;
store["abc"] = Foo("/home/data/");
std::cout << c << std::endl;
std::cout << store["abc"] << std::endl;
}
The code compiles on Linux with gcc 4.9.2. The first print correctly print out the string, but the second does not.
What is wrong with this piece of code?
Your calls to memcpy() in both the copy constructor and assignment operator are wrong. You are specifying &rhs.data_ as the source in both cases:
memcpy((char *)data_, (const char *)&rhs.data_, total_);
...
memcpy(data_, &rhs.data_, total_);
By using '&' in this manner, you are copying random bytes that immediately follow the data_ member in memory, NOT the bytes that data_ is pointing at.
Since data_ is already a pointer to the data being copied, you need to drop the & and just use rhs.data_ as-is (and there is no need for the type-casts):
memcpy(data_, rhs.data_, total_);
Alternatively, get rid of all this manual logic and just use std::string or std::vector instead, and let the compiler and STL handle all of the memory management and data copying for you:
struct Foo {
char type_; // char to label type
std::string data_; // content of memory
Foo(const char * t) : type_('c'), data_(t) {}
Foo() : type_() {}
};
inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
os << "(type: " << v.type_ << ", num: " << v.data_.length() << ", total: " << v.data_.capacity() << ", data: " << v.data_.c_str() << ", data addr: " << (void *)v.data_.data() << ")";
return os;
}
struct Foo {
char type_; // char to label type
std::vector<BYTE> data_; // content of memory
Foo(const char * t) : type_('c') { std::copy(t, t+(strlen(t)+1), std::back_inserter(data_)); }
Foo() : type_() {}
};
inline std::ostream & operator<<(std::ostream & os, const Foo & v) {
os << "(type: " << v.type_ << ", num: " << v.data_.size() << ", total: " << v.data_.capacity() << ", data: " << (const char*) &v.data_[0] << ", data addr: " << (void *)&v.data_[0] << ")";
return os;
}
I'm attempting to use boost::static_visitor to implement actions on a boost::variant type that affect the state of some variable. My approach was to contain all of the state variables in my command visitor class, but it seems this is not possible.
Here is my code example:
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t) const
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator(TypeB & t) const
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
I hope this snippet gets across the gist of what I'm trying to accomplish. It won't compile, however, giving the [paraphrased] error:
error: no operator "<<" matches these operands
operand types are: const std::stringstream << const char [N]
m_outStream << "TYPE A ACTION: " << t.varB << std::endl;
^
I'm assuming this error is due to the const modifier that must be placed on the end of the operator() function prototype which makes the compiler believe that member variables cannot be modified by the function.
My question is thus:
What is the proper way to accomplish the visitor pattern (using boost::variant) with variables that must maintain state between visits?
There were a couple of typos, but I made a few mods and it works now. Essentially your static_visitor class is mutating itself on each visit, so the operator() methods can't be const.
#include <string>
#include <sstream>
#include <vector>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
#include <iostream>
struct TypeA
{
int varA;
int varB;
};
struct TypeB
{
std::string varA;
std::string varB;
};
typedef boost::variant<TypeA, TypeB> MyVariantType;
class MyCommandVisitor : public boost::static_visitor<>
{
public:
//These are just examples, the actions only need to be able to touch
// internal variables.
void operator()(TypeA & t)
{
m_runningSum += t.varA;
m_outStream << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator()(TypeB & t)
{
m_charCount += t.varA.size();
m_outStream << t.varB << " ACTION " << t.varA << std::endl;
}
std::string emitWork(std::vector<MyVariantType> listOfVariants)
{
m_outStream.clear();
m_runningSum = 0;
m_charCount = 0;
BOOST_FOREACH(MyVariantType & v, listOfVariants)
{
boost::apply_visitor(*this, v);
}
return m_outStream.str();
}
protected:
int m_runningSum;
int m_charCount;
std::stringstream m_outStream;
}; //End class MyCommandVisitor
int main(int argc, char **argv)
{
TypeA ta;
ta.varA = 1;
ta.varB = 2;
TypeB tb;
tb.varA = "String1";
tb.varB = "String2";
std::vector<MyVariantType> listOfWork;
listOfWork.push_back(ta);
listOfWork.push_back(tb);
MyCommandVisitor myCV;
std::string result = myCV.emitWork(listOfWork);
std::cout << "Result:\n" << result << std::endl << std::endl;
return 0;
}
running on http://www.compileonline.com/compile_cpp11_online.php gives:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
Result:
TYPEA ACTION: 2
String2 ACTION String1
I'd personally favour making the functor const. Instead, I like to bind the functor arguments to references:
static std::string emitWork(std::vector<MyVariantType> const listOfVariants) {
int sum = 0, charCount = 0;
std::stringstream os;
BOOST_FOREACH(MyVariantType const& v, listOfVariants) {
boost::apply_visitor(
boost::bind(MyCommandVisitor(), _1, boost::ref(os), boost::ref(sum), boost::ref(charCount)),
v);
}
return os.str();
}
Note that
emitWork can now be static, reentrant etc.
the operator() can now be const
The rest of the visitor would look like this:
struct MyCommandVisitor : boost::static_visitor<> {
void operator()(TypeA const& t, std::stringstream& os, int& sum, int& /*charCount*/) const {
sum += t.varA;
os << "TYPEA ACTION: " << t.varB << std::endl;
}
void operator()(TypeB const& t, std::stringstream& os, int& /*sum*/, int& charCount) const {
charCount += t.varA.size();
os << t.varB << " ACTION " << t.varA << std::endl;
}
};
See it Live On Coliru