Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Serialisation of STL-container - fails with maps...

Reply
Thread Tools

Serialisation of STL-container - fails with maps...

 
 
Jorge Schramm
Guest
Posts: n/a
 
      10-07-2003
Hi,

a collegue of mine is trying to write a serialisable container (reads at
construction, writes at destruction).
The writing part is pretty easy: simply iterate through the container and
write into the file.
Reading from the file is (should) be easy too:
while you're getting data from the file (stream) insert it into your
container.
Unfortunatly this fails with the container map, because the
map::value_type's key is const :-/

This is the stripped code:

#include <list>
#include <vector>
#include <map>
#include <set>
#include <deque>

template< class containerT >
class MyContainer : public containerT
{
public:
void read()
{
typename containerT::value_type val;

/* normally:
read from file and make the assigment,
this is simply for demonstration
*/
val = val;

/* insert into container */
insert(end(), val);
}
};


template< class containerT >
void foo()
{
MyContainer< containerT > cont;
cont.read();
}

int main(int, char**)
{
/* compiles */
foo< std::vector< int > >();
foo< std::list< char > >();
foo< std::set< char > >();
foo< std::deque< long > >();

/* fails */
foo< std::map< char, int > >();
return 0;
}


Any ideas, how to modify the code for being able to assign to the value and
add to the container??

The read function would look something like this:

void read()
{
std::ifstream stream(m_path.c_str());
while (!stream.eof())
{
typename containerT::value_type val;
stream >> val;
insert(end(), val);
}
}

Thanks in advance
Jorge
 
Reply With Quote
 
 
 
 
Attila Feher
Guest
Posts: n/a
 
      10-07-2003
Jorge Schramm wrote:
> Hi,
>
> a collegue of mine is trying to write a serialisable container (reads
> at construction, writes at destruction).
> The writing part is pretty easy: simply iterate through the container
> and write into the file.
> Reading from the file is (should) be easy too:
> while you're getting data from the file (stream) insert it into your
> container.
> Unfortunatly this fails with the container map, because the
> map::value_type's key is const :-/

[SNIP]
> Any ideas, how to modify the code for being able to assign to the
> value and add to the container??

[SNIP]

Try to find it. If found, erase it. Then insert. This is the way to do it
with map and set.

--
Attila aka WW


 
Reply With Quote
 
 
 
 
Jorge Schramm
Guest
Posts: n/a
 
      10-07-2003
Hi Attila,

thanks for your answer.

> Try to find it. If found, erase it. Then insert. This is the way to do
> it with map and set.


Unfortunately this is not the problem :-/ The line with the assignment fails
compiling for std::map.

| typename containerT::value_type val;
| val = val; // fails


This is because the value_type of map is a pair, having its key *const*.
I'd like to know an alternative

Jorge
 
Reply With Quote
 
Attila Feher
Guest
Posts: n/a
 
      10-07-2003
Jorge Schramm wrote:
> Hi Attila,
>
> thanks for your answer.
>
>> Try to find it. If found, erase it. Then insert. This is the way
>> to do it with map and set.

>
> Unfortunately this is not the problem :-/ The line with the
> assignment fails compiling for std::map.
>
>> typename containerT::value_type val;
>> val = val; // fails

>
> This is because the value_type of map is a pair, having its key
> *const*. I'd like to know an alternative


The right eay to do it (or alternative as you call it) is to search for the
key part. If you find it, delete it. Then insert the new.

PSEUDO CODE!

void read()
{
typedef typename containerT::value_type value_type;
typedef typename containerT::iterator iterator;
// read key and value
iterator it = this->find(key);
if (key != this->end()) {
this->erase(key);
}
this->insert(end(), make_pair(key,value));
}

BTW do *not* inherit from the conatiner! Have it as a member. By
inheriting from it you wonder to two-phase name lookup land and *all* the
names coming from the container has to be prefixed with typename or this->
to make sure it will work.

--
Attila aka WW


 
Reply With Quote
 
Attila Feher
Guest
Posts: n/a
 
      10-07-2003
Attila Feher wrote:
> BTW do *not* inherit from the conatiner! Have it as a member. By
> inheriting from it you wonder to two-phase name lookup land and *all*
> the names coming from the container has to be prefixed with typename
> or this-> to make sure it will work.


Update. You will still need typename before the types if it is a member.
But since it is a member you will not run into trouble by leaving out the
this-> before the member function calls. If you do leave out (and the
compiler "starts" to support two phase name lookup) you can end up calling
the std::find instead of the members etc. In addition your container class
is not a map (if I understand it right), it is implemented in terms of a map
(or whatever container you use).

BTW I suggest you read Scott Meyers Effective STL and Item #2, Beware of the
illusion of container independent code.

--
Attila aka WW


 
Reply With Quote
 
tom_usenet
Guest
Posts: n/a
 
      10-07-2003
On Tue, 07 Oct 2003 13:42:25 +0200, Jorge Schramm
<(E-Mail Removed)> wrote:

>Hi,
>
>a collegue of mine is trying to write a serialisable container (reads at
>construction, writes at destruction).
>The writing part is pretty easy: simply iterate through the container and
>write into the file.
>Reading from the file is (should) be easy too:
>while you're getting data from the file (stream) insert it into your
>container.
>Unfortunatly this fails with the container map, because the
>map::value_type's key is const :-/


Here's a version that works on MSVC7.1. It won't work on earlier
versions, since they don't support partial specialization, which is
required to solve this problem (there may be an MSVC6 solution - I'll
have a fiddle).

Container persistence systems have been done before. You might want to
check out progress of the boost serialization library (see the files
section of www.boost.org)

#include <list>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <fstream>

template <class T>
struct value_traits
{
typedef T value_type;
typedef T non_const_value_type;

static std::istream& get_from_stream(std::istream& is,
non_const_value_type& t)
{
is >> t;
return is;
}
};

template <class T, class U>
struct value_traits<std:air<T const, U> >
{
typedef std:air<T const, U> value_type;
typedef std:air<T, U> non_const_value_type;
static std::istream& get_from_stream(std::istream& is,
non_const_value_type& t)
{
is >> t.first >> t.second;
return is;
}
};

template< class containerT >
class MyContainer : public containerT
{
public:
std::string m_path;

void read()
{
std::ifstream stream(m_path.c_str());
typedef value_traits<typename containerT::value_type> traits;
typename traits::non_const_value_type val;
while (traits::get_from_stream(stream, val))
{
this->insert(this->end(), val);
}
}
};


template< class containerT >
void foo()
{
MyContainer< containerT > cont;
cont.read();
}

int main(int, char**)
{
/* compiles */
foo< std::vector<int> >();
foo< std::list<char> >();
foo< std::set<char> >();
foo< std::deque<long> >();

/* fails */
foo< std::map<char, int> >();
return 0;
}
 
Reply With Quote
 
Jorge Schramm
Guest
Posts: n/a
 
      10-07-2003
Hi tom_usenet,

thanks! Works on Linux with gcc 3.2.2 too
Nice idea using partial specialisation!!

Jorge
 
Reply With Quote
 
Jorge Schramm
Guest
Posts: n/a
 
      10-08-2003
tom_usenet wrote:

> Here's a version that works on MSVC7.1. It won't work on earlier
> versions, since they don't support partial specialization, which is
> required to solve this problem (there may be an MSVC6 solution - I'll
> have a fiddle).


*argh* my collegue uses msvc 6.0 :/

We made a workaround with a load-policy. It's not very nice but it works.

template< class containerT, typename loadPolicyT = defaultLoadPolicy >
class MyContainer : public containerT
{
void read()
{
std::ifstream stream(m_path.c_str());
loadPolicy::load(stream, *this);
}
}


Thx,
Jorge
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
XML Serialisation problem - sending a business object over a webservice Nick Gilbert ASP .Net 4 05-25-2005 03:32 PM
Serialisation problem on customised object ickz Java 1 05-13-2005 08:32 AM
What is vanilla serialisation called? VisionSet Java 1 07-03-2004 06:08 PM
Axis client side data serialisation question. Michael Binz Java 0 10-29-2003 07:22 PM
Serialisation inefficiency Roedy Green Java 8 09-18-2003 07:48 PM



Advertisments