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 noinit_adaptor.qbk]
|
||||||
[include noncopyable.qbk]
|
[include noncopyable.qbk]
|
||||||
[include null_deleter.qbk]
|
[include null_deleter.qbk]
|
||||||
|
[include nvp.qbk]
|
||||||
[include pointer_traits.qbk]
|
[include pointer_traits.qbk]
|
||||||
[include quick_exit.qbk]
|
[include quick_exit.qbk]
|
||||||
[include ref.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_throws_test.cpp ;
|
||||||
run alloc_construct_cxx11_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 ;
|
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 ;
|
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