Deserialize a const member object in a constructor - c++

I need to initialize the const member object of a class in a constructor, but the member's constructor creates just an empty object, whereas real initialization has to be done by deserialization of this object from a file. The class of the member object is not mine and I can't change it. Namely, it's a Dlib model, the following code simulates it's behavior:
#include <iostream>
#include <string>
// not my class, can't be changed
class ShapePredictor
{
friend std::istream& operator >> (std::istream& stream, ShapePredictor&);
public:
ShapePredictor() = default;
ShapePredictor(const ShapePredictor& other) : data(other.data) { std::cout << "copy" << std::endl; }
ShapePredictor(ShapePredictor&& other) : data(std::move(other.data)) { std::cout << "moved" << std::endl; }
private:
std::string data;
};
// deserialization
std::istream& operator >> (std::istream& stream, ShapePredictor& sp)
{
sp.data = "test33";
return stream;
}
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> this->sp; // won't compile
}
private:
const ShapePredictor sp;
};
int main(int argc, char* argv[])
{
FaceExtractor extractor;
return 0;
}
I am not sure what is the best way to do it. The first thing that springs to mind is using const_cast<>():
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> const_cast<ShapePredictor&>(this->sp);
}
private:
const ShapePredictor sp;
};
It works, but using const_cast<>() is normally considered a bad practice. I read it is mostly designed for compatibility with legacy APIs that are not const correct. I am not quite sure whether it would be ok to use it in my case.
Another way to tackle it is to create a member function deserialize() which would load the class into a temporary object and return it:
class FaceExtractor
{
public:
FaceExtractor()
: sp(deserialize())
{ }
ShapePredictor deserialize()
{
ShapePredictor tmp;
std::cin >> tmp;
return tmp;
};
private:
const ShapePredictor sp;
};
This involves creating a temporary, which is undesirable. Hopefully, NRVO will elide a copy, but in MSVC it still costs one additional move.
I am wondering what is the common practice to initialize such kind of objects?

Just make the member variable non-const. Having const member variables is usually a pain and is rarely useful.
if you absolutely must have it const, you could make a class that inherits from ShapePredictor and add a constructor that does the streaming.
struct ShapePredictorStreamable : public ShapePredictor {
ShapePredictorStreamable(std::istream& is) {
is >> *this;
}
};
class FaceExtractor {
public:
FaceExtractor() : sp(std::cin) {}
private:
const ShapePredictorStreamable sp;
};

Related

How can I static cast the output of the >> operator in c++?

Or perform any function really.
Currently I have some code that looks a bit like this:
int temp_int;
streamer >> temp_int;
finalObj = static_cast<CustomType>(temp_int);
ints can be cast into CustomTypes (obviously) and finalObj is of type CustomType
streamer's >> operator has not been set up to work with CustomType. Changing this is outside my area of control.
Im looking for a way to put the above code in a single line and avoid using a temporary variable.
When putting custom types back into the streamer, I use this:
streamer << static_cast<int>(someObj);
Thats a lot neater. And it would be great to have the instreaming and outstreaming look symmetrical for easier reading.
Thanks
Just implement an operator>> and make sure name lookup finds it.
struct CustomType
{
int m_value;
CustomType(int v = 0)
: m_value(v)
{}
operator int() const
{
return m_value;
}
};
namespace
{
std::istream& operator>>(std::istream& s, CustomType& out)
{
int temp;
s >> temp;
out = temp;
return s;
}
}
int main()
{
CustomType finalObj;
std::cin >> finalObj;
std::cout << finalObj << '\n';
}
Alternatively, if you aren't sure, if operator>> has already been implemented somewhere in an undesired manner, you could create a wrapper type and implement operator>> for it.
namespace
{
class CustomTypeParsingWrapper
{
public:
CustomTypeParsingWrapper(CustomType& target)
: m_target(target)
{
}
friend std::istream& operator>>(std::istream& s, CustomTypeParsingWrapper const& wrapper)
{
int temp;
s >> temp;
wrapper.m_target = temp;
return s;
}
private:
CustomType& m_target;
};
}
int main()
{
CustomType finalObj;
std::cin >> CustomTypeParsingWrapper(finalObj);
std::cout << finalObj << '\n';
}
Note: The use of the anonymous namespace here is only to avoid conflicts with implementations provided to other translation units. If you want to reuse operator>>, you should put it in the same namespace as CustomType to allow Argument Dependent Lookup to find it. A customTypeParsingWrapper intended to be reused could be put in a namespace of your choice...
One way to achieve what you want is to overload not only << and >> operators, but also the cast operator.
One way to do that is to overload the int() operator for CustomType. This way, you can use put your value back into the streamer easily:
class CustomType
{
private:
int _value;
public:
CustomType(const int &value) : _value(value) {}
// ...
operator int() const { return _value; }
};
This way, the compiler will find the appropriate cast from CustomType to int when using the << operator:
streamer << someObj;
will implicitly cast to int.
Similar overloads could be implemented to achieve the results.
Here is a full snipped to test this:
#include <iostream>
class CustomType
{
private:
int _value;
public:
CustomType(const int &value) : _value(value) {}
// ...
operator int() const { return _value; }
};
int main() {
auto someObj = CustomType(10);
std::cout << someObj;
}
This prints 10 to the standard output.

How do I use a stream extraction operator if a default constructor isn't provided?

I have a software engineering question in relation to C++, constructors (default and otherwise), the stream extraction operator, and reference member variables. I know that is a lot of topics, but all of them seem to depend on each other in this problem.
For a problem that I am trying to solve, I wanted to make a Vec class which holds the data for the problem, and a ProblemSolver class which will eventually have methods to solve the problem. The ProblemSolver class doesn't make sense without the data, so I wrote it with a copy of the Vec data (considerations for reference member occurred later...). So here was what my first version looked like:
#include <iostream>
#include <vector>
class Vec {
private:
std::vector<int> v;
public:
Vec(const int s) : v(s, 0) { }
};
class ProblemSolver {
private:
Vec data;
public:
ProblemSolver(Vec d) : data(d) { }
};
int main() {
int m;
std::cin >> m;
Vec v(m);
ProblemSolver ps(v);
}
So far this seemed okay. Then I though that I should provide stream extraction operators for each class so that the objects could be in charge of reading in its own data instead of reading it in main. So I rewrote the classes like this:
#include <iostream>
#include <vector>
class Vec {
private:
std::vector<int> v;
public:
Vec(const int s) : v(s, 0) { }
friend std::istream& operator >> ( std::istream& input, Vec &V ) {
int m;
input >> m;
V.v = std::vector<int>(m, 0);
return input;
}
};
class ProblemSolver {
private:
Vec data;
public:
ProblemSolver(Vec d) : data(d) { }
friend std::istream& operator >> ( std::istream& input, ProblemSolver &P ) {
input >> P.data;
return input;
}
};
int main() {
ProblemSolver p;
std::cin >> p;
}
This is where I ran into some confusion because the first line of main() is trying to call the default constructor for ProblemSolver. I understand that it's an issue because one isn't provided, but what should I really do about this in terms of good practice for my problem above? Should I always provide a default constructor, even though the class doesn't make sense without an actual set of data? Was I wrong that I should just let the object handle its own data reading, and that I shouldn't write the stream extraction operators?
Because of this article, I considered using a reference member variable instead because the "data for the problem solver class still exists outside of the existence of the instances of the problem solver". So I again rewrote it like this:
#include <iostream>
#include <vector>
class Vec {
private:
std::vector<int> v;
public:
Vec(const int s) : v(s, 0) { }
friend std::istream& operator >> ( std::istream& input, Vec &V ) {
int m;
std::cin >> m;
V.v = std::vector<int>(m, 0);
return input;
}
};
class ProblemSolver {
private:
const Vec& v;
public:
ProblemSolver(const Vec& v_) : v(v_) { }
};
int main() {
int m;
std::cin >> m;
Vec v(m);
ProblemSolver p(v);
}
But with this, I still can't write a stream extraction operator for ProblemSolver and the one written for Vec is practically useless because I'd have to instantiate a Vec object before I can use the stream extraction operator. Therefore in the example above I still have to read the int m data in main() and I can't do something like Vec v; std::cin >> v; ProblemSolver p(v); for the same reasons as in the second code segment. I think it should be possible to do something like instantiating and reading in a variable all at once like std::cin >> ProblemSolver p;, but obviously that isn't the case.
So my primary question is how do I properly write these two classes? Should I include default constructors? My understanding is that I shouldn't provide a default constructor if the class doesn't make sense without any data, but is that wrong? If I don't write a default constructor, should I instantiate a class with useless data provided to the standard constructor just so that I can then use the stream extraction operator on it? That seems like a bad practice to instantiate an object falsely before stream extraction.
To be clear, I'm not just looking for just a solution that works. I'd like to develop actual good practice and techniques for situations like these, so please support your answer with justification.
In this case, the object must be constructed first.
Some options are:
have a default costructor which construts with a default value (maybe 0).
have a constructor which takes reference to istream which will then use it to load values.
so something like:
class Vec {
private:
std::vector<int> v;
public:
Vec(const int s) : v(s, 0) { }
Vec(std::istream& input)
{
int m;
input >> m;
v = std::vector<int>(m, 0);
}
friend std::istream& operator >> ( std::istream& input, Vec &V ) {
int m;
input >> m;
V.v = std::vector<int>(m, 0);
return input;
}
};
class ProblemSolver {
private:
Vec v;
public:
ProblemSolver(Vec v_) : v(v_) { }
ProblemSolver() : v(0) { }
ProblemSolver(std::istream& in) : v(in) { }
};
If you are adamant that the class will not make sense without a value, you will be better of writing a generator function and abandoning the stream extraction operator. like so:
class Vec {
private:
std::vector<int> v;
public:
Vec(const int s) : v(s, 0) { }
};
class ProblemSolver {
private:
Vec data;
public:
ProblemSolver(Vec d) : data(d) { }
static ProblemSolver generate()
{
int m;
std::cin >> m;
return ProblemSolver{Vec{m}};
}
};
int main() {
ProblemSolver p = ProblemSolver::generate();
}

Template functions by index in C++

Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}

c++ about operator* overloading

Is there any possible way to overload operator* in such way that it's assigning and observing functions are defined apart?
class my_class
{
private:
int value;
public:
int& operator*(){return value;}
};
int main()
{
my_class obj;
int val = 56;
*obj = val; // assign
val = *obj; // observe, same operator* is called
}
Sort of -- you can have the operator* return an instance of another class, rather than returning a reference directly. The instance of the other class then defines both a conversion operator and an assignment operator.
(In your sample code, it looks like you've overloaded the multiplication operator when you meant to overload the dereferencing operator; I'll use the dereferencing operator below.)
For example:
class my_class
{
friend class my_class_ref;
public:
my_class_ref operator*() { return my_class_ref(this); }
private:
int value;
};
class my_class_ref
{
public:
operator int() { return owner->value; } // "observe"
my_class_ref& operator=(int new_value) { owner->value = new_value; return *this; } // "assign"
private:
my_class* owner;
my_class_ref(my_class* owner) { this->owner = owner; }
};
There are some caveats. For example, as my_class_ref is implemented with a pointer to its parent class, your code must be careful that my_class_ref always has a lifetime shorter than the lifetime of the corresponding my_class -- otherwise you will dereference an invalid pointer.
In practice, if you pretend that my_class_ref doesn't exist (i.e. never declare a variable with that class) it can work very well.
Write your class like so
class my_class
{
private:
int value;
public:
int operator*() const { // observing
return value;
}
int& operator*() { // assigning
return value;
}
};
Then these operators are dissambiguated by constness, so code like this is possible
int _tmain(int argc, _TCHAR* argv[])
{
my_class a;
*a = 1; // assigning
int k = *(const_cast<my_class const&>(a)); // observing
return 0;
}

Storing vector of pointers in a file and reading them again

Assume the following code:
// Base class
class Base {
public:
Base(int val) : hi(val) {
}
virtual void PublicMethod() { /* Do something */}
private:
int hi;
};
// Child class
class Child : public Base {
public:
Child(int val) : Base(val) {
}
void PublicMethod() { /* Do something */}
};
// Vector of pointers to prevent slicing
std::vector<std::shared_ptr<Base>> list;
(...) // Fill list with mixed data of class Base and Child
After the list is filled with objects, I want to store the data into a file. For this I tried the following:
std::ofstream os("data.txt", std::ios::out);
int size1 = list.size();
os.write((const char*)&size1, sizeof(int));
for (auto it = list.begin(); it < list.end(); ++it) {
os.write((const char*)(*it), size1 * sizeof(Base));
}
os.close();
However I am not sure if this is correct, and reading the data from the file also doesn't seem to work properly. I am afraid that when I'm saving the data sizeof(Base) also doesn't work for its child objects which might no be of the same size.
Even if this works correctly, are there better ways of storing the actual data into a file, and how can I easily read the data from the file and store them in a shared_ptr<Base> vector list?
Any examples would be of great help.
You need to provide some form of serialization for your objects. Here's a very trivial example (that leaves out error checking, type construction etc.)
This example shows most primitive type of serialization, but it will suffice to provide an example of what you need to do.
When you start dealing with derived classes, it becomes more tricky, as you will need some factory method to properly create the types, based on some sentinel value that you serialize.
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
class A
{
public:
A()
: a_(0)
{
}
A(int a, const string& n)
: a_(a), n_(n)
{
}
// a function to write objects to a stream
friend ostream& operator<<(ostream& stream, const A& obj);
// a function to read objects from a stream
friend istream& operator>>(istream& stream, A& obj);
private:
int a_;
string n_;
};
ostream& operator<<(ostream& out, const A& obj)
{
out << obj.a_ << ' ' << obj.n_;
return out;
}
istream& operator>>(istream& in, A& obj)
{
in >> obj.a_ >> obj.n_;
return in;
}
int main()
{
A one(1, "one");
A also_one;
string buffer;
stringstream serializer;
// write out your source object to a stream and "store it"
// here we simply store it in a string
serializer << one;
buffer = serializer.str();
// using the "stored" value, read the stored values
// into an (already constructed) object
stringstream deserializer(buffer);
serializer >> also_one;
// verify the output is the same
cout << one << " is the same as " << also_one << "\n";
}