forked from boostorg/core
Implement NVP in Core for Serialization and other libraries
This commit is contained in:
@ -55,6 +55,7 @@ criteria for inclusion is that the utility component be:
|
||||
[include noinit_adaptor.qbk]
|
||||
[include noncopyable.qbk]
|
||||
[include null_deleter.qbk]
|
||||
[include nvp.qbk]
|
||||
[include pointer_traits.qbk]
|
||||
[include quick_exit.qbk]
|
||||
[include ref.qbk]
|
||||
|
126
doc/nvp.qbk
Normal file
126
doc/nvp.qbk
Normal file
@ -0,0 +1,126 @@
|
||||
[/
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section:nvp nvp]
|
||||
|
||||
[section Overview]
|
||||
|
||||
The header <boost/core/nvp.hpp> provides the class template `boost::nvp` that
|
||||
pairs a name (`const char*`) with the address of a value (`T*`). It is the new
|
||||
implementation of the NVP type previously provided by the Boost Serialization
|
||||
library. This type now lives in the Core library so that other Boost libraries
|
||||
can support named value serialization without taking a dependency on the
|
||||
Serialization library.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Examples]
|
||||
|
||||
The following snippet shows use in a member serialize function:
|
||||
|
||||
```
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned)
|
||||
{
|
||||
archive & boost::make_nvp("x", x_) & boost::make_nvp("y", y_);
|
||||
}
|
||||
```
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Reference]
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class nvp {
|
||||
nvp(const char* name, T& value) noexcept;
|
||||
|
||||
const char* name() const noexcept;
|
||||
|
||||
T& value() const noexcept;
|
||||
|
||||
const T& const_value() const noexcept;
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& archive, unsigned) const;
|
||||
|
||||
template<class Archive>
|
||||
void load(Archive& archive, unsigned);
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive& archive, unsigned);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_nvp;
|
||||
|
||||
template<class T>
|
||||
const nvp<T> make_nvp(const char* name, T& value) noexcept;
|
||||
|
||||
} /* boost */
|
||||
```
|
||||
|
||||
[section Constructors]
|
||||
|
||||
[variablelist
|
||||
[[`nvp(const char* name, T& value) noexcept;`]
|
||||
[Initializes the stored name pointer with `name` and the value pointer with
|
||||
`addressof(value)`.]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Members]
|
||||
|
||||
[variablelist
|
||||
[[`const char* name() const noexcept;`]
|
||||
[Returns the stored name pointer.]]
|
||||
[[`T& value() const noexcept;`]
|
||||
[Returns the stored value pointer.]]
|
||||
[[`const T& const_value() const noexcept;`]
|
||||
[Returns the stored value pointer.]]
|
||||
[[`template<class Archive> void save(Archvie& archive, unsigned) const;`]
|
||||
[Calls `archive.operator<<(const_value())`.]]
|
||||
[[`template<class Archive> void load(Archvie& archive, unsigned);`]
|
||||
[Calls `archive.operator>>(value())`.]]
|
||||
[[`template<class Archive> void serialize(Archvie& archive,
|
||||
unsigned version);`]
|
||||
[Calls `save(archive, version)` if `Archive::is_saving` is a true type,
|
||||
otherwise `load(archive, version)`.]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Traits]
|
||||
|
||||
[variablelist
|
||||
[[`template<class T> class is_nvp;`]
|
||||
[Provides static constant `value` equal to true if `T` is an NVP type,
|
||||
otherwise false.]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Functions]
|
||||
|
||||
[variablelist
|
||||
[[`template<class T> const nvp<T> make_nvp(const char* name, T& value)
|
||||
noexcept;`]
|
||||
[Returns `nvp<T>(name, value)`.]]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
Robert Ramey originally implemented nvp in the Serialization library. Glen
|
||||
Fernandes implemented this new (but compatible) version in the Core library.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
113
include/boost/core/nvp.hpp
Normal file
113
include/boost/core/nvp.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef BOOST_CORE_NVP_HPP
|
||||
#define BOOST_CORE_NVP_HPP
|
||||
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template<bool V>
|
||||
struct nvp_bool {
|
||||
typedef bool value_type;
|
||||
typedef nvp_bool type;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = V);
|
||||
|
||||
BOOST_CONSTEXPR operator bool() const BOOST_NOEXCEPT {
|
||||
return V;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool operator()() const BOOST_NOEXCEPT {
|
||||
return V;
|
||||
}
|
||||
};
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T>
|
||||
class nvp {
|
||||
public:
|
||||
nvp(const char* n, T& v) BOOST_NOEXCEPT
|
||||
: n_(n)
|
||||
, v_(boost::addressof(v)) { }
|
||||
|
||||
const char* name() const BOOST_NOEXCEPT {
|
||||
return n_;
|
||||
}
|
||||
|
||||
T& value() const BOOST_NOEXCEPT {
|
||||
return *v_;
|
||||
}
|
||||
|
||||
const T& const_value() const BOOST_NOEXCEPT {
|
||||
return *v_;
|
||||
}
|
||||
|
||||
template<class A>
|
||||
void save(A& a, unsigned) const {
|
||||
a.operator<<(*v_);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
void load(A& a, unsigned) {
|
||||
a.operator>>(*v_);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
void serialize(A& a, unsigned) {
|
||||
archive(a, detail::nvp_bool<A::is_saving::value>());
|
||||
}
|
||||
|
||||
private:
|
||||
template<class A>
|
||||
void archive(A& a, detail::nvp_bool<true>) const {
|
||||
a.operator<<(*v_);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
void archive(A& a, detail::nvp_bool<false>) {
|
||||
a.operator>>(*v_);
|
||||
}
|
||||
|
||||
const char* n_;
|
||||
T* v_;
|
||||
};
|
||||
|
||||
template<class>
|
||||
struct is_nvp
|
||||
: detail::nvp_bool<false> { };
|
||||
|
||||
template<class T>
|
||||
struct is_nvp<nvp<T> >
|
||||
: detail::nvp_bool<true> { };
|
||||
|
||||
template<class T>
|
||||
struct is_nvp<const nvp<T> >
|
||||
: detail::nvp_bool<true> { };
|
||||
|
||||
template<class T>
|
||||
struct is_nvp<volatile nvp<T> >
|
||||
: detail::nvp_bool<true> { };
|
||||
|
||||
template<class T>
|
||||
struct is_nvp<const volatile nvp<T> >
|
||||
: detail::nvp_bool<true> { };
|
||||
|
||||
template<class T>
|
||||
inline const nvp<T>
|
||||
make_nvp(const char* n, T& v) BOOST_NOEXCEPT
|
||||
{
|
||||
return nvp<T>(n, v);
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
@ -145,6 +145,8 @@ run alloc_construct_test.cpp ;
|
||||
run alloc_construct_throws_test.cpp ;
|
||||
run alloc_construct_cxx11_test.cpp ;
|
||||
|
||||
run nvp_test.cpp ;
|
||||
|
||||
lib lib_typeid : lib_typeid.cpp : <link>shared:<define>LIB_TYPEID_DYN_LINK=1 ;
|
||||
|
||||
run test_lib_typeid.cpp lib_typeid : : : <link>shared : test_lib_typeid_shared ;
|
||||
|
123
test/nvp_test.cpp
Normal file
123
test/nvp_test.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
class saver {
|
||||
public:
|
||||
struct is_saving {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
explicit saver(int value)
|
||||
: value_(value) { }
|
||||
|
||||
int get() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
void operator<<(int value) {
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
class loader {
|
||||
public:
|
||||
struct is_saving {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
explicit loader(int value)
|
||||
: value_(value) { }
|
||||
|
||||
void operator>>(int& value) {
|
||||
value = value_;
|
||||
}
|
||||
|
||||
private:
|
||||
int value_;
|
||||
};
|
||||
|
||||
void test()
|
||||
{
|
||||
const char* n = "name";
|
||||
int v = 1;
|
||||
boost::nvp<int> p(n, v);
|
||||
BOOST_TEST_EQ(p.name(), n);
|
||||
BOOST_TEST_EQ(p.value(), 1);
|
||||
BOOST_TEST_EQ(&p.value(), &v);
|
||||
}
|
||||
|
||||
void test_save()
|
||||
{
|
||||
int v = 1;
|
||||
boost::nvp<int> p("name", v);
|
||||
saver s(0);
|
||||
p.save(s, unsigned());
|
||||
BOOST_TEST_EQ(s.get(), 1);
|
||||
}
|
||||
|
||||
void test_load()
|
||||
{
|
||||
int v = 1;
|
||||
boost::nvp<int> p("name", v);
|
||||
loader l(5);
|
||||
p.load(l, unsigned());
|
||||
BOOST_TEST_EQ(p.value(), 5);
|
||||
}
|
||||
|
||||
void test_serialize()
|
||||
{
|
||||
int v = 1;
|
||||
boost::nvp<int> p("name", v);
|
||||
saver s(0);
|
||||
p.serialize(s, unsigned());
|
||||
BOOST_TEST_EQ(s.get(), 1);
|
||||
}
|
||||
|
||||
void test_deserialize()
|
||||
{
|
||||
int v = 1;
|
||||
boost::nvp<int> p("name", v);
|
||||
loader l(5);
|
||||
p.serialize(l, unsigned());
|
||||
BOOST_TEST_EQ(p.value(), 5);
|
||||
}
|
||||
|
||||
void test_trait()
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((boost::is_nvp<boost::nvp<double> >));
|
||||
BOOST_TEST_TRAIT_FALSE((boost::is_nvp<double>));
|
||||
BOOST_TEST_TRAIT_TRUE((boost::is_nvp<const boost::nvp<int> >));
|
||||
BOOST_TEST_TRAIT_FALSE((boost::is_nvp<const int>));
|
||||
}
|
||||
|
||||
void test_factory()
|
||||
{
|
||||
const char* n = "name";
|
||||
int v = 1;
|
||||
boost::nvp<int> p = boost::make_nvp(n, v);
|
||||
BOOST_TEST_EQ(p.name(), n);
|
||||
BOOST_TEST_EQ(p.value(), 1);
|
||||
BOOST_TEST_EQ(&p.value(), &v);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
test_save();
|
||||
test_load();
|
||||
test_serialize();
|
||||
test_deserialize();
|
||||
test_trait();
|
||||
test_factory();
|
||||
return boost::report_errors();
|
||||
}
|
Reference in New Issue
Block a user