Boost logo

Boost :

From: Dave Harris (brangdon_at_[hidden])
Date: 2002-11-22 16:07:35


In-Reply-To: <20021122143347.GB408_at_[hidden]>
On Fri, 22 Nov 2002 15:33:47 +0100 Wesley W. Terpstra
(terpstra_at_[hidden]) wrote:
> You will not need any hooks; to fully bracket the data, you can use a
> type-conversion trick made concrete below.

It's a neat trick, but I'd rather not rely on tricks. I might want:

    ar << one << two << three;
    //...
    ar << four << five << six;
    return ar;

to all be serialized as a single group. I'd rather have a clean design at
bottom, with a layer of tricks on top for people who want the convenience.
Eg:

    ar << start_group();
    ar << one << two << three;
    //...
    ar << four << five << six;
    ar << end_group();
    return ar;

or:

    grouper raii(ar);
    ar << one << two << three;
    //...
    ar << four << five << six;
    return ar;

or:

    return grouper(ar) << one << two << three << four << five << six;

all producing the same archive data.

> Yes; I had proposed in an earlier email a seperate serializor which
> included the name strings:
> return o << "bar" << bar << "foo" << foo ...
>
> This would provide the needed names to the system.

As I understood it, this also relied on a trick - on the XML oarchive
assuming that alternate writes were names rather than values. If we sent
the same output to a different oarchive, it presumably wouldn't make that
assumption and they would be treated as values and repeated in the data of
each object serialised. That is quite an overhead. The alternative, that
non-XML archives also ignore alternate string writes, is bad too because
one archive format should not have to work to indulge vagarities of
another. A third alternative, for the object to somehow know when it is
writing to an XML archive and serialise differently, is also bad.

I think such tricks are a bad way to go. I would much rather have
something explicit like:
    ar << tag("bar") << bar << tag("foo") << foo;

where the oarchive has a virtual function for writing tags. This also
allows:
   ar << tag("point") << x << y;

where there is no need for the tags to alternate with values.

It'd be possible to implement such stuff on top of the current submission,
without adding virtual functions to the base classes, by using
dynamic_cast. Eg:

    struct tag {
        tag( const char *str ) : str(str) {}
        const char *str;
    };
    
    basic_oarchive &operator>>( basic_oarchive &ar, const tag &t ) {
        if (basic_tagged_oarchive *p =
                 dynamic_cast<basic_tagged_oarchive *>( &ar ))
             p->tag( t.str );
        return ar;
    }

where basic_tagged_oarchive inherits from basic_oarchive, and xml_oarchive
inherits from basic_tagged_oarchive. (I imagine there may be other types
of tagged archive, such as for HTML or for human-readable output, such
as debugging or error-logging.)

Personally I'd rather add the virtual functions, because I prefer to avoid
dynamic_cast<>. I'd rather have dynamic_cast<> than make assumptions about
alternate writes, though.

Really we are just talking about 3 functions: start_group(), end_group()
and tag(). People who don't need XML output wouldn't need to use them. In
practice I think using them would help a lot in producing human readable
output. We could probably get rid of the newline() function, for example.

-- Dave Harris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk