Support to-object conversions for std::reference_wrapper<const T>.

Previously the conversion would fail because struct object is not
generally provided for the const version of the type, but because
the wrapper would pass down the type unchanged, it would look for
exactly that missing template specialization unsuccessfully.

This is specifically an issue for std::reference_wrapper because
std::cref() returns an std::reference_wrapper<const T>.
This commit is contained in:
Jakob Petsovits 2015-11-11 18:16:44 -05:00
parent 0a261fca42
commit b5599ef3fc
2 changed files with 40 additions and 3 deletions

View File

@ -24,6 +24,7 @@
#include "msgpack/adaptor/check_container_size.hpp" #include "msgpack/adaptor/check_container_size.hpp"
#include <memory> #include <memory>
#include <type_traits>
namespace msgpack { namespace msgpack {
@ -53,14 +54,14 @@ struct pack<std::reference_wrapper<T>> {
template <typename T> template <typename T>
struct object<std::reference_wrapper<T> > { struct object<std::reference_wrapper<T> > {
void operator()(msgpack::object& o, const std::reference_wrapper<T>& v) const { void operator()(msgpack::object& o, const std::reference_wrapper<T>& v) const {
msgpack::adaptor::object<T>()(o, v.get()); msgpack::adaptor::object<typename std::remove_const<T>::type>()(o, v.get());
} }
}; };
template <typename T> template <typename T>
struct object_with_zone<std::reference_wrapper<T>> { struct object_with_zone<std::reference_wrapper<T>> {
void operator()(msgpack::object::with_zone& o, const std::reference_wrapper<T>& v) const { void operator()(msgpack::object::with_zone& o, const std::reference_wrapper<T>& v) const {
msgpack::adaptor::object_with_zone<T>()(o, v.get()); msgpack::adaptor::object_with_zone<typename std::remove_const<T>::type>()(o, v.get());
} }
}; };

View File

@ -17,7 +17,20 @@ TEST(MSGPACK_REFERENCE_WRAPPER, pack_convert)
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size()); msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
int i2 = 0; int i2 = 0;
std::reference_wrapper<int> val2(i2); std::reference_wrapper<int> val2(i2);
oh.get().convert(val2);; oh.get().convert(val2);
EXPECT_EQ(i1, i2);
}
TEST(MSGPACK_REFERENCE_WRAPPER, pack_convert_const)
{
const int i1 = 42;
std::reference_wrapper<const int> val1(i1);
std::stringstream ss;
msgpack::pack(ss, val1);
msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
int i2 = 0;
std::reference_wrapper<int> val2(i2);
oh.get().convert(val2);
EXPECT_EQ(i1, i2); EXPECT_EQ(i1, i2);
} }
@ -44,6 +57,17 @@ TEST(MSGPACK_REFERENCE_WRAPPER, object)
EXPECT_EQ(i1, i2); EXPECT_EQ(i1, i2);
} }
TEST(MSGPACK_REFERENCE_WRAPPER, object_const)
{
const int i1 = 42;
std::reference_wrapper<const int> val1(i1);
msgpack::object o(val1);
int i2 = 0;
std::reference_wrapper<int> val2(i2);
o.convert(val2);
EXPECT_EQ(i1, i2);
}
TEST(MSGPACK_REFERENCE_WRAPPER, object_with_zone) TEST(MSGPACK_REFERENCE_WRAPPER, object_with_zone)
{ {
std::string s1 = "ABC"; std::string s1 = "ABC";
@ -56,4 +80,16 @@ TEST(MSGPACK_REFERENCE_WRAPPER, object_with_zone)
EXPECT_EQ(s1, s2); EXPECT_EQ(s1, s2);
} }
TEST(MSGPACK_REFERENCE_WRAPPER, object_with_zone_const)
{
const std::string s1 = "ABC";
std::reference_wrapper<const std::string> val1(s1);
msgpack::zone z;
msgpack::object o(val1, z);
std::string s2 = "DE";
std::reference_wrapper<std::string> val2(s2);
o.convert(val2);
EXPECT_EQ(s1, s2);
}
#endif // !defined(MSGPACK_USE_CPP03) #endif // !defined(MSGPACK_USE_CPP03)