How to use streams in abstract classes - c++

This might seem like an opinion question but I'm really looking for some good ways to go about doing this. so what's this? I basically want to have an abstract class named Repo let's say. This class is going to define the abstraction for what a Repo should be capable of doing. In this case, I just want to be able to save something, say you provide a name and data and it's supposed to store it for you. Then we can have a FileRepository that would save them on disc, S3Repository for example to store them in the AWS S3, or even MemoryRepository where we just save them in the memory.
Great, but how do I abstract this out? obviously I could get the bytes and each derived class would use their own stream to save it but what if the data is large and we don't want to load it up in the memory? let's say we want to save a 5GB file, we don't want to load that up in the memory.
I looked at the AWS SDK for C++ and it seems like they take a lambda with an ostream in it so you can write content. I tried to mimic something like that here so you can either just pass your istream, or give a lambda that takes an ostream and does whatever its heart desires.
Just wondering if there is a better way for this? it's often difficult to find good practices in c++ since there are a billion ways to do the same thing and many people do things very differently. I'd just love some insight here. I'm fairly new to C++ so a good explanation would be highly appreciated.
class Repo {
public:
virtual void add_with_ostream(const string& name, const std::function<void (ostream&)>& f) = 0;
template<typename T>
void add(const string& name, const T& data) {
this->add_with_ostream(name, [&data](ostream& output_stream) {
output_stream << data;
});
}
virtual void add_with_istream(const string&name, const istream& input_stream) {
this->add_with_ostream(name, [&input_stream](ostream& output_stream) {
output_stream << input_stream.rdbuf();
});
}
};

Related

What is the best way to represent a single global class instance?

I have a project, which has its own filesystem. The class basically looks like this:
class ResourceManager {
public:
std::string readFile(std::string const&);
private:
std::vector<std::string> root;
};
This class is used everywhere in the project. So it's global and have a single instance. My current solution is that I create an instance in the main function and then pass it to all of my classes (they store a reference). I'm absolutely fine with this approach, besides that i need to pass the instance to regular functions, but I'm curious if it's possible to archive a better result.
A simple way of making a filesystem is just to have static functions, because you don't really need any variables to store. But in my case I have a variable called root, which stores search directories so that I can do something like this:
rm.addResourceRoot(ResourceType::images, "path/to/directory");
I can have a static variable ResourceManager* instance and method ResourceManager& getRm() { return *instance; } inside a class, but that approach feels kind of weird and probably isn't a "best practice". Probably outside-of-class functions like this will help to make it look better, but I'm still hesitating.
std::string readFile(std::string const& path) {
return ResourceManager::getRm().readFile(path);
}
I can use singleton pattern, but everyone convinces me not to use it, because it's an anti-pattern and not good solution at all. This confuses me in some way so it would be great if anyone could explain the reasons to me.
In my opinion, the ideal access should look like this:
ResourceManager::readFile("path/to/file");
So what is the best way to represent such entities in a project?

Can I avoid dynamic_cast when subclasses define new member variables?

I'm trying to write an application in a "modern" C++ style, while at the same time trying to learn how to do so, and have gotten stuck on a design issue that should be fairly basic.
The application indexes various things, such as files/folders, music (via some music player API, not the filesystem) and perhaps in the future bookmarks and so on.
The issue comes in representing these things. My plan was to use a base class, e.g. IndexedObject, which I then subclass into something like IndexedFile, IndexedSong and so on.
These kinds of objects need to have some members in common, and some not. All kinds need an icon and a name to display in the application, so those clearly go in IndexedObject. However, an indexed file needs a full path, whereas an indexed song needs artist, album and title, but we might not know its path (it might not even be located on disk). Storing all of this in a single class seems very ugly, and in that case, I would still need a "type" member to figure out what a particular class instance is supposed to represent.
For the parts of the program where I have an IndexedObject but need to access the information only a particular subclass such as IndexedFile knows about, is there a better option than using dynamic_cast, or is this exactly when it should be used?
By "better", I mean for any reasonable definition of better, such as having higher performance, being safer, and so on. Other options may well include an altogether different design, by the way. This base class/subclass design was just the first thing I thought of.
Update:
A few commenters asked to provide code. However, I don't really have much code that is relevant to this particular question; the question is how I should design and code this (whether the subclass approach is even the right one). I could be super-specific in what I need, but then the answers would become near-useless for anyone other than myself.
I could provide a bit of extra detail about what the goal is, though, so read on if you want that.
The program indexes the various things mentioned in the background, and stores them in an some container type (QVector in my case) for easy retrieval. The user brings the app up via some hotkey, and types in search terms. For each typed letter, the app filters the index, and displays the matches.
For each match found, the UI needs to know its type. If it's a song, perhaps we want to format that as "artist - track name (from album)" or something; if it's a bookmark, perhaps show the domain name and part of the URL, and so on.
So in other words, if I use the subclass method, I might do something like:
// The real code would of course have a bit more meat with some basic methods
class IndexedObject {
string name;
image icon;
};
class IndexedSong : public IndexedObject {
string artist;
string title;
};
class IndexedBookmark : public IndexedObject {
some_url_type url;
};
void displayObject(const IndexedObject &obj) {
// Pseudo-C++ follows
if (obj is IndexedSong) {
display icon, artist and title
}
else if (obj is IndexedBookmark) {
display icon, name and URL;
}
}
... the issue with this example is that the question isn't how to use dynamic_cast, which the example above seems to imply I must, but whether there is an entirely different way to solve this problem that avoids dynamic_cast altogether.
For your code, you could define a virtual function in the base class, and let the sub classes implement that function, which can avoid dynamic_cast. The code will be like this:
class IndexedObject {
string name;
image icon;
public:
virtual void display() = 0;
};
class IndexedSong : public IndexedObject {
string artist;
string title;
public:
virtual void display()
{/////}
};
class IndexedBookmark : public IndexedObject {
some_url_type url;
public:
virtual void display()
{/////}
};
void displayObject(const IndexedObject &obj) {
obj.display()
}
The Open-Closed principle is to deal with this case, you can find more details in the url and it talks about how to not use dynamic_cast.
Instead of using dynamic_cast, the preferred way is to put the parts that must be done differently for different classes into virtual functions. The term to look for, and learn about, is "polymorphism".
P.S. Maybe it's not a good idea to use inheritance at all - there may be songs which also are files. Composition might work better.
Polymorphic data storage types are a bit of a problem for C++, since good OOP style dictates that the polymorphic behavior should be housed in the subclasses themselves... that is, say, IndexedObject would have a pure-virtual play() function, and IndexedSong's implementation would play a song, IndexedVideo's would play a video, and so on. But if it's something else consuming the data, it's difficult to make a nice, abstract interface for that.
dynamic_cast, enumerations specifying the type, etc. are almost always employed in this situation.

Need library for binary stream serialization, C++

What I'm looking for is similar to the serialization library built into RakNet (which I cannot use on my current project). I need to be able save/load binary streams into a custom format locally, and also send them over a network. The networking part is solved, but I really don't want to write my own methods for serializing all of my different types of data into binary, especially since it would be inefficient without any compression methods.
Here's some pseudocode similar to how RakNet's bitstreams work, this is along the lines of what I'm looking for:
class Foo
{
public:
void Foo::save(BitStream& out)
{
out->write(m_someInt);
out->write(m_someBool);
m_someBar.save(out);
// Alternative syntax
out->write<int>(m_someInt);
// Also, you can define custom serialization for custom types so you can do this...
out->write<Bar>(m_someBar);
// Or this...
out->write(m_someBar);
}
void Foo::load(BitStream& in)
{
in->read(m_someInt);
in->read(m_someBool);
in->read(m_someBar);
}
private:
int m_someInt;
bool m_someBool;
Bar m_someBar;
};
Are there any free C++ libraries out there that allow for something like this? I basically just want something to pack my data into binary, and compress it for serialization, and then decompress it back into binary that I can feed back into my data.
EDIT, adding more information:
Unfortunately neither Google Protocol Buffers or Boost Serialization will work for my needs. Both expect to serialize object members, I need to simply serialize data. For example, lets say I have a std::vector<Person>, and the class Person has a std::string for name, and other data in it, but I only want to serialize and deserialize their names. With Google Protocol Buffers it expects me to give it the Person object as a whole for serialization. I can achieve however, achieve this with Boost Serialization, but if I have another scenario where I need the entire Person to be serialized, there is no way to do that, you either have to serialize all of it, or none. Basically I need quite a bit of flexibility to craft the binary stream however I see fit, I just want a library to help me manage reading and writing binary data to/from the stream, and compressing/decompressing it.
Google Protocol Buffers
Boost serialization
UPDATE
Looking at the updated question I think it might be easiest to write a small custom library that does exactly what is required. I have a similar one and it is only a few hundred lines of code (without compression). It is extremely easy to write unit tests for this kind of code, so it can be reliable from day one.
To serialize custom types, I have a Persistent base class that has save and load methods:
class Storage {
public:
void writeInt( int i );
void writeString( string s );
int readInt();
string readString();
};
class Persistent {
public:
virtual void save( Storage & storage ) = 0;
virtual void load( Storage & storage ) = 0;
};
class Person : public Persistent {
private:
int height;
string name;
public:
void save( Storage & storage ) {
storage.writeInt( height );
storage.writeString( name );
}
void load( Storage & storage ) {
storage.readInt( height );
storage.readString( name );
}
};
And then there's a simple layer on top of that that stores some type information when saving and uses a Factory to create new objects when loading.
This could be further simplified by using C++'s streams (which I don't like very much, hence the Storage class). Or copying Boost's approach of using the & operator to merge load and save into a single method.

Implement Minimal logging program in c++

I am developing a disk based tree for a database engine and i like to maintain a log file for my program. I basically need two kinds of functionality from the log program. It must allow me to log a message into a log file and also must write any variable that i pass it as an argument into the log file. I need only these two functions. The first is fairly simple to achieve but i am finding it hard to achieve the second one. I want to pass any number of arguments of any type to the log program to write it into the log file. I tried to achieve the second one using variable argument function but the problem is we must know the type of the variables that are being passed. I am sure there must be some way to do this. Can anyone enlighten me on this?
log4C++ provides the functionality you're looking for.
If that is a little too heavy weight for you you can do something similar using templates. Something like:
class log
{
private:
std::ostream& stream;
public:
log(std::ostream& src) : stream(src) {}
...
std::ostream& getStream() { return stream; }
}
template <typename T> log& operator<<(log&, const T& val)
{
log.getStream() << val;
return log;
}
Here log::stream is some std::ostream instance you defined for output to a file, to a console or whatever. You can make it a bit fancier by distinguishing between different types of logging events.
Have a look at the implementation of this simple logging system from Dr Dobs article: http://drdobbs.com/cpp/201804215
It is template based, has logging levels (that don't incur any overhead at run-time if not needed) and is small

Using xml to load objects. Which is the best approach?

TinyXML
I have a XML file that keeps a bunch of data that is loaded into objects. Right now, I have one giant method that parses the XML file and creates the appropriate objects depending on the contents of the XML file. This function is very large and imports lots of class definitions.
Would it be better to each class type to do its own loading from XML. That way the XML code is dispersed throughout my files and not in one location. The problem is that I need to pass it the exact node inside the XML file where that function should read from. Is this feasible? I'm using tinyxml so if imagine each class can be passed the XML stream (an array containing the XML data actually) and then I'd also pass the root element for that object \images\fractal\traversal\ so it knows what it should be reading.
Then the saving would work the same way.
Which approach is best and more widely used?
I don't know anything about TinyXML, but I have been using that kind of class design with libxml2 for several years now and it has been working fine for me.
Serialization functions should be friends of the classes they serialize. If you want to serialize and deserialize to XML you should write friend function that perform this function. You could even write custom ostream & operator <<() functions that do this, but this becomes problematic if you want to aggregate objects. A better strategy is to define a mechanism that turns individual objects into Node's in a DOM document.
I can think of an approach, based on a factory to serve up the objects based on a tag.
The difficulty here is not really how to decouple the deserialization of each object content, but rather to decouple the association of a tag and an object.
For example, let's say you have the following XML
<my_xml>
<bird> ... </bird>
</my_xml>
How do you know that you should build a Bird object with the content of the <bird> tag ?
There are 2 approaches there:
1 to 1 mapping, ig: <my_xml> represents a single object and thus knows how to deserialize itself.
Collection: <my_xml> is nothing more than a loose collection of objects
The first is quite obvious, you know what to expect and can use a regular constructor.
The problem in C++ is that you have static typing, and that makes the second case more difficult, since you need virtual construction there.
Virtual construction can be achieved using prototypes though.
// Base class
class Serializable:
{
public:
virtual std::auto_ptr<XmlNode*> serialize() const = 0;
virtual std::auto_ptr<Serializable> deserialize(const XmlNode&) const = 0;
};
// Collection of prototypes
class Deserializer:
{
public:
static void Register(Tag tag, const Serializable* item)
{
GetMap()[tag] = item;
}
std::auto_ptr<Serializable> Create(const XmlNode& node)
{
return GetConstMap()[node.tag()]->deserialize(node);
// I wish I could write that ;)
}
private:
typedef std::map<Tag, const Serializable*> prototypes_t;
prototypes_t& GetMap()
{
static prototypes_t _Map;
return _Map;
}
prototypes_t const& GetConstMap() { return GetMap(); }
};
// Example
class Bird: public Serializable
{
virtual std::auto_ptr<Bird> deserialize(const XmlNode& node);
};
// In some cpp (bird.cpp is indicated)
const Bird myBirdPrototype;
Deserializer::Register('bird', myBirdPrototype);
Deserialization is always a bit messy in C++, dynamic typing really helps there :)
Note: it also works with streaming, but is a bit more complicated to put in place safely. The problem of streaming is that you ought to make sure not to read past your data and to read all of your data, so that the stream is in a 'good' state for the next object :)