$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Wesley W. Terpstra (terpstra_at_[hidden])
Date: 2002-11-19 14:30:45
On Tue, Nov 19, 2002 at 06:07:23PM +0100, Wesley W. Terpstra wrote:
> The trick is to use the FUNCTION boundary of the serializor.
<snip code>
I have attached a working proto-type.
This is merely proof of concept; I am not sure whether one should bracket
fundamental types for instance.
The output is presently:
[ 1 [ 2 ] 3 4 [ 5 ] ]
but maybe should be:
[ [1] [ [2] ] [3] [4] [ [5] ] ]
What do people think?
I am certain someone smarter than I could make this even more clever.
---
Wes
//-------------------------------------------------------- Example begins
// Compiles and works with g++-2.95.4
#include <iostream>
using namespace std;
//-------------------------------------------------------- Common Framework
class object_stream;
class streamer
{
protected:
object_stream* m_impl;
streamer(object_stream* stream) : m_impl(stream) { }
public:
template <class T>
object_stream& operator << (const T& x);
friend class object_stream;
};
class object_stream
{
protected:
streamer m_helper;
virtual void object_begin() = 0;
virtual void object_end () = 0;
public:
object_stream() : m_helper(this) { }
virtual ~object_stream() { }
operator streamer& ()
{ // Casted on return from method
object_end();
return m_helper;
}
// All fundamental types go here
virtual object_stream& operator << (int x) = 0;
// This catches all non-fundamental types and safely preserves
// our type information while calling
template <class T>
object_stream& operator << (const T& x)
{ // Don't use conversion routine to cast us (not end of object)
return *(m_helper << x).m_impl;
}
friend class streamer;
};
template <class T>
object_stream& streamer::operator << (const T& x)
{
m_impl->object_begin();
return *m_impl << x;
}
//-------------------------------------------------------- Concrete streamer
class paran_object_stream : public object_stream
{
protected:
void object_begin() { cout << "[ "; }
void object_end () { cout << "] "; }
public:
paran_object_stream& operator << (int x)
{ cout << x << " "; return *this; }
};
class paran_streamer : public streamer
{
protected:
paran_object_stream m_obj;
public:
paran_streamer()
: streamer(&m_obj) // a bit bad since it is not init'd, but since
{ } // we won't do anything in the base-class, ok
};
//-------------------------------------------------------- Generic user
struct Foo
{
int x;
};
streamer& operator << (streamer& o, const Foo& f)
{ return o << f.x; }
struct Bar
{
int a;
Foo b;
int c;
int d;
Foo e;
};
streamer& operator << (streamer& o, const Bar& b)
{ return o << b.a << b.b << b.c << b.d << b.e; }
//-------------------------------------------------------- test
int main()
{
Bar b;
b.a = 1;
b.b.x = 2;
b.c = 3;
b.d = 4;
b.e.x = 5;
paran_streamer s;
s << b;
cout << endl;
}