Boost logo

Boost :

From: David B. Held (dheld_at_[hidden])
Date: 2003-02-07 12:18:08


"Peter Dimov" <pdimov_at_[hidden]> wrote in message
news:008b01c2cea4$172cb700$1d00a8c0_at_pdimov2...
> David B. Held wrote:
> > I need a pointer that can store pointer or an ID.
>
> Looks like a variant. Out of curiosity, how do you use it?

Yeah, it is a variant of two types: an int and some pointer of your
choice. The only things it gives you that most variants don't (that
I'm aware of), is automagic operator->(), and implicit conversion
to int and the pointer type (not sure if that's bad or not). So the
way I wanted to use it (with some context to motivate it) is to,
say, stick a bunch of them in a container. For argument's sake,
let's just use std::vector:

typedef std::vector<serial_ptr<my_data> > my_table;

So let's say we get a result set from a database over a network,
but we cache records. So instead of sending over whole records,
it only sends over IDs (primary key), and we can ask for the rest
of the data if we don't have it cached already. So a very raw
illustration might be something like this:

my_table employees_; // cached records

void get_records(recordset_type r)
{
    my_table employees;
    while (!r.eof())
    {
        int id = r.current_id();
        my_table::iterator i = find(
            employees_.begin(), employees_.end(), id
        );
        if (i == employees_.end())
        {
            employees.push_back(id);
        }
        else
        {
            employees.push_back(*i);
        }
        r.next();
    }
}

Later on, if you need data from a record, and you only have an
ID, you can fetch the whole record and replace the ID. This
allows for lazy caching of data from relational databases, where
fetching a complete record could involve touching ten tables and
performing multiple lookup queries.

Now, you might wonder how find() works. Well, with the code
given, it doesn't. That's because I forgot to put in a function that
tells you what the current tag is, but also because I don't really
intend to use it with std::vector. I actually used it in a different
context before, that involved serializing off a disk, and there, I
didn't need to know the tag type because I could deduce what
it ought to be from the program flow. But in my current use-
case, I do need to be able to query the tag type. Also, an
operator*() might be nice, but I didn't have a need for it before.

So thereafter, you might use it like so:

my_data& get_employee(int id)
{
    my_table::iterator i = find(
        employees_.begin(), employees_.end(), id
    );

    if (i == employees_.end()) throw exception("employee not found");
    if (i->tag == my_table::t_id)
    {
        fetch_employee_record(id); // get full record over the network,
            // and cache it
    }
    return *i;
}

Hopefully, you get an idea for my intent, even though the code
here is assuming a lot of things.

Dave


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