The best way to write code to load/save vectors of custom classes

I'd want to write a fast code to load /save vectors of custom classes.
Both to-from memory and to-from disk.

I have (in example)
struct mydata { int one, double two }
vector <mydata> my_vector_of_data

Ok, I'cant write to disk the whole vector, isn't ? (without looping on it.. )
So, How can I do the work ? A stringstream object and << >> operations can be a way ?
Thanks
Check out Boost.Serialization.
And there is no other solution ?
Thanks
Use std::streams. The stream is a concept that has several implementations as you have seen: It can be a stream to a string, it can be a stream to a file, etc. Just write the inner state data of the class to a stream and you are done! I would define an IStream pure virtual class (BTW, COM has an IStream interface that you should use if you are developing COM).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class IStream
{
    //Very simplified:
public:
    virtual void Load(istream &is) = 0;
    virtual void Save(ostream &os) = 0;
};

class MyClass : public IStream
{
    ....
    //IStream:
public:
    virtual void Load(istream &is)
    {
        //Code to load from input string goes here.
    }
    virtual void Save(ostream &os)
    {
        //Code to write to the stream goes here.
    }
};


Now your code that has access to the vector or other collection can just iterate through the collection of objects, dynamic_cast<IStream&>, and just call Load() or Save() with the appropriately created string.
However in that case you will not have a compilation error, but run-time error (if you're lucky)
I think it is better to define a template of methods that the class will have in order to be serialised (like save and load methods).
Then create the operators << and >> against the streams.
To containers you could use copy.
1
2
3
4
5
6
7
8
9
10
template<class Iter>
void print(std::ostream &out, Iter begin, Iter end){
	std::copy(
		begin,
		end,
		std::ostream_iterator
			<typename std::iterator_traits<Iter>::value_type>
			(out, " ")
	);
}


Now, ¿why you don't want to use boost?

changed write for print
Last edited on
I'm having trouble in defining the operator<< for containers. (in order to print something like vector<vector<int> >)
I could do something like
1
2
3
4
5
6
7
namespace std{
	template<class T>
	std::ostream& std::operator<<(std::ostream &out, const std::vector<T> &v){
		print(out, v.begin(), v.end());	
		return out;
	}
}
But then I will need to write almost the same for list, deque, map, set, ...

¿Is there a way to know if an object is a container, so it can choose the proper function?

changed write for print
Last edited on
Write the same...? No, if all the containers/classes you use will compile when you substitute T with the container type, then you have no worries, unless you have a second personality that likes to use template functions with types it can't support. Just do this:
1
2
template<class T>
std::ostream& std::operator<<(std::ostream &out, const T &v)

And assume that it is a container that supports the begin() and end() functions - also you may need to specialize the template for maps.
Last edited on
The problem is that that is the specialization that I use for custom types.*
1
2
3
4
5
6
7
8
9
class foo{
public:
	void print(std::ostream &out);
};

template<class T>
std::ostream& std::operator<<(std::ostream &out, const T &a){
	a.print(out);
}


*I know that the operator can be friend of the class, and it will not need the write print method.
Topic archived. No new replies allowed.