Boost logo

Boost :

Subject: Re: [boost] [serialization] rvalues and const-correctness?
From: David Abrahams (dave_at_[hidden])
Date: 2008-11-09 15:54:32


on Sun Nov 09 2008, "Robert Ramey" <ramey-AT-rrsd.com> wrote:

> David Abrahams wrote:
>
>>> The member function wasn't my point at all. I just want to be able
>>> to save rvalues.
>
> OK - I think I see the problem better. It would seem that you want
> to serialize a temporay value from the stack. Think about what this
> would mean in the context of pointers and object tracking. Since
> tracking is done via object address, and tracking is necessary
> in order to implement correct restoration of pointers, this can't
> can't be done reliably.

I didn't think you did object tracking for things that were serialized
by value. Do you do that?

>> Have you had a chance to look into this? I've been using a patched
>> version of the library that adds the stated overload and it is working
>> great. Taking out the patch means that where I ought to have been
>> able to simply write
>>
>> ar << f();
>
> what does f() return?

An rvalue.

> I would expect it return a reference to a constant object of some
> sort. If it doesn't, then I would expect that its possible that now
> or sometime in the future, unloadable archives could be created. And
> the fact that these archives are unloadable would not be discovered
> until the are in fact actually loaded. Also it would be extremely
> difficult to determine what the problem is. Finally, it would be very
> difficult to fixup the archive.
>
> Of course the fact that in many particular cases it doesn't create
> a problem doesn't alleviate my concerns.

Naturally.

>> I am forced to write code like this:
>>
>> typename nasty_trait_to_compute_return_type<foo>::type x = f();
>> ar << x;
>
> If this function is called more than once, then it's possible that
> the address of the second object serialized will be the same as that
> of the first call and only an object id will be saved even if the object
> is in fact different,

In my case I've turned off tracking, but yeah.

> This is implemented this way to support efficient
> and correct serialization of pointers and incidently to save storage.
> In this instance, an archive will be created such that when the second
> object is loaded, it will be identical to the first object and this
> will not be correct.

Yes, I'm aware of the tracking functionality.

> This error would be a major problem to find. So I would not recommend
> your fix above. A better way would be to restrict f() to function
> which return a const reference to the type returned by the current
> f().

I suppose I could also wrap the return type in a "wrapper type":

  template <class T>
  struct wrap_rvalue
  {
      wrap_rvalue(T const& x) : x(x) {}
      T x;
  };

  template <class T>
  wrap_rvalue<T> rval(T const& x) { return wrap_rvalue<T>(x); }

  namespace boost { namespace serialization {
    template <class T>
    struct is_wrapper<wrap_rvalue<T> > : mpl::true_ {};
  }}

  ar << rval( f() );

> If that isn't convenient, and one had nothing else to do, he could
> explore the implications of implementing your proposed specialization
> so that it traps at compile time if the object might be tracked. This
> would mean that something like int f() would work while something
> like my_object f() would likely trap unless my_object was specifically
> marked as no_tracking. Thinking about this just a tiny bit makes
> this seem attractive to me. Of course that doesn't mean much
> until one sets out to actually do it.

That's actually pretty easy to do; something like:



-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com


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