Boost logo

Boost Users :

From: Robert Ramey (ramey_at_[hidden])
Date: 2006-08-07 11:41:34


My understanding of the standard is that this operation is legal but that
the compiler
writer has the option of using a copy operation to implement it.

a) As far as I know - no compiler we've used has done this.
b) nvp is a "wrapper" in that it is just a holder for the underlying values
to be
serialized - so making a copy of this wrapper would do no harm.

This issue has provoked a lot of problematic behavior between compilers.
I'm not
sure whether the current situation is the result of evolution to universal
functionality or just an original oversight which has never been addressed.
It's interesting to consider - but not urgent as it has no practical impact
on the operation of the library.

Note that microsoft vc compilers of late are in the habit of emitting
warning messages alledging "deprecated" or non-standard behavior
where none exists. Also, some standard behavior (e.g. two-phase
lookup) is not implemented by microsoft compilers. So using
a microsoft C++ compiler (Or any particular compiler) as a definitive
test for code conformance to the standard is ill-advised.

Robert Ramey

"Stephen Hewitt" <shewitt.au_at_[hidden]> wrote in message
news:c7c622110608070558o56184437v8a57320a0510171_at_mail.gmail.com...
The following is a dead simple example of using Boost.Serialization using an
XML output archive which follows the patterns laid down in examples:

/*
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
*/
#include <iostream>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/nvp.hpp>

// Warning level 4.
#pragma warning(push, 4)
#pragma message("********")

struct MyData
{
    MyData(int val) : m_Value(val) {}

    template<typename Archive>
    void serialize(Archive & ar, const unsigned int)
    {
        ar & BOOST_SERIALIZATION_NVP(m_Value); // <-- Warning here.
    }

    int m_Value;
};

void main()
{
    using namespace std;

    MyData d(3);
    boost::archive::xml_oarchive oa(cout);
    oa << BOOST_SERIALIZATION_NVP(d); <-- Warning here.
}

// Warning level back to normal.
#pragma warning(pop)
/*
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
*/

When compiling this code I get the following error:
 "warning C4239: nonstandard extension used : 'argument' : conversion from
'struct boost::serialization::nvp<struct MyData>' to 'struct
boost::serialization::nvp<struct MyData> &'
        A reference that is not to 'const' cannot be bound to a non-lvalue"

I tried MSVC 6 and "Visual C++ 2005" which can be downloaded from here:
        http://msdn.microsoft.com/vstudio/express/visualC/default.aspx
Interestingly I could not get it to happen with "Microsoft Visual C++
Toolkit 2003".

The warning seems valid to me. The "BOOST_SERIALIZATION_NVP" looks like
this:
--------------------------------------------------------------------------------------------------------------------------
#define BOOST_SERIALIZATION_NVP(name) \
    boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name)
--------------------------------------------------------------------------------------------------------------------------

The "make_nvp" function looks like as follows:
-------------------------------------------------------
nvp<T> make_nvp(const char * name, T & t){
    return nvp<T>(name, t);
}
-------------------------------------------------------

"Operator<<", which is used in "main" is reproduced below:
--------------------------------------------------------------------------------------
template<class Archive>
class interface_oarchive
{
// ... Code removed ... //
template<class T>
    Archive & operator<<(T & t){
        this->This()->save_override(t, 0);
        return * this->This();
    }
// ... Code removed ... //
};
--------------------------------------------------------------------------------------

So, to cut to the chase, "BOOST_SERIALIZATION_NVP" expands to a call to
make_nvp" which returns a temporary which is bound to a non-const reference
in "interface_oarchive::operator<<": this is not legal in standard C++
(unless I'm mistaken).

It seems that if you follow to documentation and examples the resulting code
isn't standard C++!?!

_______________________________________________
Boost-users mailing list
Boost-users_at_[hidden]
http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net