Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#3977 closed Patches (wontfix)

Compile error on make_nvp with reference data member

Reported by: kondo@… Owned by: Robert Ramey
Milestone: Boost 1.43.0 Component: serialization
Version: Boost 1.42.0 Severity: Problem
Keywords: Cc:

Description

When I save the reference data member to the xml_archive by using make_nvp, the compile error occurs.

Attached file 'ref_direct.cpp' is an example program to reproduce problem.

    // Compile error!
    ar << boost::serialization::make_nvp("ref_", &p->ref_);

The error message is below.

error: invalid initialization of non-const reference of type ‘MyInt*&’ from a temporary of type ‘MyInt*'

We can avoid this error using additional variable or using static_cast.

    // OK
    MyInt* pRef = &p->ref_;
    ar << boost::serialization::make_nvp("ref_", pRef);
    // OK
    ar << boost::serialization::make_nvp("ref_", static_cast<const MyInt * const &>(&p->ref_));

But I think it's not elegant.

My idea is that introducing the new overload of make_nvp function template.

template<class T>
inline
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
const
#endif
nvp<const T> make_nvp(const char * name, const T & t){
    return nvp<const T>(name, t);
}

It resolves this problem.

Please check 'nvp_const_ref.patch' (attached file).

After apply the patch, I already did the regression test of serialization. All test is passed.

My testing environments are g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1 and VC++ 9.0 on Windows7.

Attachments (4)

ref_direct.cpp (2.2 KB ) - added by kondo@… 13 years ago.
an example program to reproduce problem
nvp_const_ref.patch (631 bytes ) - added by kondo@… 13 years ago.
patch file to resolve this problem
ref_direct2.cpp (2.4 KB ) - added by kondo@… 13 years ago.
replace TAB to white space version of ref_direct.cpp
nvp_const_ref_ptr_special.patch (637 bytes ) - added by kondo@… 13 years ago.
improved patch file

Download all attachments as: .zip

Change History (10)

by kondo@…, 13 years ago

Attachment: ref_direct.cpp added

an example program to reproduce problem

by kondo@…, 13 years ago

Attachment: nvp_const_ref.patch added

patch file to resolve this problem

comment:1 by anonymous, 13 years ago

Component: Noneserialization
Owner: set to Robert Ramey

by kondo@…, 13 years ago

Attachment: ref_direct2.cpp added

replace TAB to white space version of ref_direct.cpp

comment:2 by kondo@…, 13 years ago

Sorry, In ref_direct.cpp, white spaces and TABs are mixed. I replace all TABs to white spaces in ref_direct2.cpp The program meaning is not changed.

comment:3 by Robert Ramey, 13 years ago

Resolution: invalid
Status: newclosed

this is not an error.

It's telling you not to pass a non-const.

try fixing it with a const_cast instead.

Your fix will actually create an error in some instances. The test suite doesn't test this specifically.

comment:4 by kondo@…, 13 years ago

Resolution: invalid
Status: closedreopened

Thank you for a quick answer.

It's telling you not to pass a non-const. try fixing it with a const_cast instead.

You're right.

I used the static_cast, and it works correctly.

  ar << boost::serialization::make_nvp("ref_", static_cast<MyInt * const &>(&p->ref_));

Your fix will actually create an error in some instances. The test suite doesn't test this specifically.

Oh, I overlooked the side effect.

My overload matches to temporary object that shouldn't match.

boost::serialization::make_nvp("MyInt", MyInt());

I still think that I can remove the cast from the client code without a side effect.

I improved my patch to match only object that should match.(nvp_const_ref_ptr_special.patch)

It matches only address of object, it no longer doesn't match temporary objects.

How do you think about it?

Of course I carried out all tests again.

And all of them succeeded.

by kondo@…, 13 years ago

improved patch file

comment:5 by Robert Ramey, 13 years ago

Resolution: wontfix
Status: reopenedclosed

This looks much better.

But I have still have concerns about it.

The reason that we trap a attempt to serialize a non-const is described in the rationale section of the documentation. Your fix overrides that an makes it easier for a user to create an archive which will prove to be unloadable. The current situation requires that the user either change his ref to a const ref or use a const_cast - also he could suppress tracking for that type. So the current situation requires that the user react to a potentially sever problem and take some explicit action to get around it. This saves me uncountable hours of explaining to the user where his problem might be when he later tries to load a tracked item which has changed in the course of serialization. I realize that it's a pain in many cases. But I really can't spend this much time with users who have inadvertently created unloadable archives.

Robert Ramey

comment:6 by kondo@…, 13 years ago

Now, I have understood your policy. Serializing the reference data member is asymmetric. And we should write such code. But my patch helps hide the such code.

Now, I think to prepare below cast in my code.

template <typename T>
T* const& reference_serialize_cast(T* const& t)
{
    return t;
}
    ar << boost::serialization::make_nvp("ref_", reference_serialize_cast(&p->ref_));

By the way,

The reason that we trap a attempt to serialize a non-const is described in the rationale section of the documentation

means http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/rationale.html ?

or you mean http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/serialization.html#references ?

Note: See TracTickets for help on using tickets.