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"
}
Related
I'm trying to figure out how to save and load an objects state to a binary stream. For context, we currently have this working but only a 'save-to-file' implementation. However, we want the serialization done in-memory to better interact with some parallelization libraries. I'm hoping this will be quite simple but my current implementation doesn't do much - can anybody spot what I'm doing wrong?
class ForSerializationAsBinary {
public:
ForSerializationAsBinary() = default;
explicit ForSerializationAsBinary(int number)
: number_(number) {}
std::ostringstream toBinaryStream() {
std::ostringstream out(std::ios::binary);
out.write((char *) &number_, sizeof(int));
return out;
}
static void fromBinaryStream(ForSerializationAsBinary &obj, std::ostringstream &os) {
int n;
std::istringstream is(std::ios::binary);
is.basic_ios<char>::rdbuf(os.rdbuf());
is.read((char *) &n, sizeof(int));
std::cout << "n: " << n << std::endl;
obj.number_ = n;
}
int number_;
};
TEST(Serialisation, SimpleSerialization) {
ForSerializationAsBinary serializationAsBinary(4);
auto o = serializationAsBinary.toBinaryStream();
ForSerializationAsBinary loaded;
ForSerializationAsBinary::fromBinaryStream(loaded, o);
std::cout << "loaded.number_: " << loaded.number_ << std::endl;
}
And the current output of the test
n: 0
loaded.number_: 0
Looks like I found the answer : just use a std::stringstream instead of the o or i versions:
class ForSerializationAsBinary {
public:
ForSerializationAsBinary() = default;
explicit ForSerializationAsBinary(int number)
: number_(number) {}
std::stringstream toBinaryStream() {
std::stringstream out(std::ios::binary);
out.write((const char *) &number_, sizeof(int));
return out;
}
static void fromBinaryStream(ForSerializationAsBinary &obj, std::stringstream &os) {
int n;
os.read((char *) &n, sizeof(int));
std::cout << "n: " << n << std::endl;
obj.number_ = n;
}
int number_;
};
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;
}
I want to implement a function like this
double d = string_to("1223.23",double);
int i = string_to("1223",int);
bool d = string_to("1",bool);
How can I pass the bool, int, double data type to implement this in c++?
Types line int, double and bool can only be passed as template parameters.
You can use templates like this:
#include <string>
#include <sstream>
#include <iostream>
template<typename DataType>
DataType string_to(const std::string& s)
{
DataType d;
std::istringstream(s) >> d; // convert string to DataType
return d;
}
int main()
{
double d = string_to<double>("1223.23");
int i = string_to<int>("1223");
bool b = string_to<bool>("1");
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
As an alternative you can pass your numeric types by reference and rely on function overloading to select the correct function:
void string_to(const std::string& s, double& d)
{
d = std::stod(s);
}
void string_to(const std::string& s, int& i)
{
i = std::stoi(s);
}
void string_to(const std::string& s, bool& b)
{
std::istringstream(s) >> std::boolalpha >> b;
}
int main()
{
double d;
int i;
bool b;
string_to("1223.23", d);
string_to("1223", i);
string_to("true", b);
std::cout << "d: " << d << '\n';
std::cout << "i: " << i << '\n';
std::cout << "b: " << b << '\n';
}
Also you could templatize the second method (an exercise for the reader).
If you really want to do this, you can pass the type by using the typeid operator.
E.g. double d = string_to("1223.23", typeid(double));
Using the library functions atoi, stod would make more sense.
If you're aiming to write more uniform code then you could write a Converter object and use method overloading to get automatic selection by type.
class Converter
{
public:
void fromString(double& value, const char* string);
void fromString(int& value, const char* string);
void fromString(long& value, const char* string);
};
Here's another way that uses tag dispatching. You can compile and run this example.
#include <iostream>
#include <string>
#include <cmath>
namespace detail {
// declare the concept of conversion from a string to something
template<class To>
To string_to(const std::string&);
// make some models of the concept
template<>
int string_to<int>(const std::string& s) {
return atoi(s.c_str());
}
template<>
double string_to<double>(const std::string& s) {
return atof(s.c_str());
}
template<>
std::string string_to<std::string>(const std::string& s) {
return s;
}
// ... add more models here
}
// define the general case of conversion from string with a model tag
// note the unused parameter allows provision of a model that is never used
// thus the model will in all likelihood be optimised away
template<class To>
To string_to(const std::string& from, const To& /* model_tag is unused */)
{
// dispatch to correct conversion function using the To type
// as a dispatch tag type
return detail::string_to<To>(from);
}
using namespace std;
int main()
{
// examples
int a = string_to("100", a);
double b = string_to("99.9", b);
const string s = string_to("Hello", s);
cout << s << " " << a << " " << b << endl;
return 0;
}
output:
Hello 100 99.9
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
I'm learning about struct types in C++ and I tried to write a function that would change the values of the members of a struct type variable.
However, it produces an unexpected output and I can't figure out why this is happening.
/Program to test struct types/
#include <iostream>
#include <cstring>
using namespace std;
struct myStruct
{
string a;
string b;
int c;
float d;
};
void assignValues(myStruct myobj)
{
myobj.a = "foobar";
myobj.b = "Foo Bar";
myobj.c = 12;
myobj.d = 15.223;
}
int main()
{
myStruct x;
cout << x.a <<endl;
//x.a = "Hello world";
//x.b = "This is C++";
//x.c = 10;
//x.d = 13.1332;
assignValues(x);
cout << x.a<<endl;
cout << x.b << endl;
cout << x.c << endl;
cout << x.d << endl;
}
If I use the individual assignment statements, (that I have commented out in the code) instead of the assignValues() function, I get the expected output.
PS: The values I expected for the output are as follows:
foobar,
Foo Bar,
12,
15.223
Pass myStruct argument by reference to assignValue function, so it can be modified:
void assignValues(myStruct& myobj)
^^^ pass by reference
{
myobj.a = "foobar";
myobj.b = "Foo Bar";
myobj.c = 12;
myobj.d = 15.223;
}
Although you can pass a pointer to function:
void assignValues(myStruct* myobj) //<---- pointer
{
myobj->a = "foobar";
myobj->b = "Foo Bar";
myobj->c = 12;
myobj->d = 15.223;
}