Fixed conflict between boost fusion sequence and std::tuple/std::pair.

This commit is contained in:
Takatoshi Kondo
2017-07-26 10:24:17 +09:00
parent 315bbd4b40
commit 7ad743f2da
2 changed files with 78 additions and 4 deletions

View File

@@ -15,6 +15,8 @@
#include "msgpack/adaptor/check_container_size.hpp" #include "msgpack/adaptor/check_container_size.hpp"
#include "msgpack/meta.hpp" #include "msgpack/meta.hpp"
#include "msgpack/adaptor/pair.hpp"
#if !defined (MSGPACK_USE_CPP03) #if !defined (MSGPACK_USE_CPP03)
#include "msgpack/adaptor/cpp11/tuple.hpp" #include "msgpack/adaptor/cpp11/tuple.hpp"
#endif // #if !defined (MSGPACK_USE_CPP03) #endif // #if !defined (MSGPACK_USE_CPP03)
@@ -34,13 +36,54 @@ MSGPACK_API_VERSION_NAMESPACE(v1) {
namespace adaptor { namespace adaptor {
namespace detail {
template <typename T>
struct is_std_pair {
static bool const value = false;
};
template <typename T, typename U>
struct is_std_pair<std::pair<T, U> > {
static bool const value = true;
};
#if !defined(MSGPACK_USE_CPP03)
template <typename T>
struct is_std_tuple {
static bool const value = false;
};
template <typename... Args>
struct is_std_tuple<std::tuple<Args...>> {
static bool const value = true;
};
#endif // !defined(MSGPACK_USE_CPP03)
template <typename T>
struct is_seq_no_pair_no_tuple {
static bool const value =
boost::fusion::traits::is_sequence<T>::value
&&
!is_std_pair<T>::value
#if !defined (MSGPACK_USE_CPP03)
&&
!is_std_tuple<T>::value
#endif // !defined (MSGPACK_USE_CPP03)
;
};
} // namespace detail
#if !defined (MSGPACK_USE_CPP03) #if !defined (MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct as< struct as<
T, T,
typename msgpack::enable_if< typename msgpack::enable_if<
boost::fusion::traits::is_sequence<T>::value && detail::is_seq_no_pair_no_tuple<T>::value &&
boost::mpl::fold< boost::mpl::fold<
T, T,
boost::mpl::bool_<true>, boost::mpl::bool_<true>,
@@ -82,7 +125,7 @@ struct as<
#endif // !defined (MSGPACK_USE_CPP03) #endif // !defined (MSGPACK_USE_CPP03)
template <typename T> template <typename T>
struct convert<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > { struct convert<T, typename msgpack::enable_if<detail::is_seq_no_pair_no_tuple<T>::value>::type > {
msgpack::object const& operator()(msgpack::object const& o, T& v) const { msgpack::object const& operator()(msgpack::object const& o, T& v) const {
if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); } if (o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }
if (o.via.array.size != checked_get_container_size(boost::fusion::size(v))) { if (o.via.array.size != checked_get_container_size(boost::fusion::size(v))) {
@@ -106,7 +149,7 @@ private:
}; };
template <typename T> template <typename T>
struct pack<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > { struct pack<T, typename msgpack::enable_if<detail::is_seq_no_pair_no_tuple<T>::value>::type > {
template <typename Stream> template <typename Stream>
msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const T& v) const { msgpack::packer<Stream>& operator()(msgpack::packer<Stream>& o, const T& v) const {
uint32_t size = checked_get_container_size(boost::fusion::size(v)); uint32_t size = checked_get_container_size(boost::fusion::size(v));
@@ -128,7 +171,7 @@ private:
}; };
template <typename T> template <typename T>
struct object_with_zone<T, typename msgpack::enable_if<boost::fusion::traits::is_sequence<T>::value>::type > { struct object_with_zone<T, typename msgpack::enable_if<detail::is_seq_no_pair_no_tuple<T>::value>::type > {
void operator()(msgpack::object::with_zone& o, const T& v) const { void operator()(msgpack::object::with_zone& o, const T& v) const {
uint32_t size = checked_get_container_size(boost::fusion::size(v)); uint32_t size = checked_get_container_size(boost::fusion::size(v));
o.type = msgpack::type::ARRAY; o.type = msgpack::type::ARRAY;

View File

@@ -212,4 +212,35 @@ TEST(MSGPACK_BOOST, pack_convert_no_def_con_def_con)
#endif // !defined(MSGPACK_USE_CPP03 #endif // !defined(MSGPACK_USE_CPP03
#include <boost/fusion/include/std_pair.hpp>
TEST(MSGPACK_BOOST, fusion_pack_unpack_convert_pair)
{
std::stringstream ss;
std::pair<bool, int> val1(false, 42);
msgpack::pack(ss, val1);
msgpack::object_handle oh =
msgpack::unpack(ss.str().data(), ss.str().size());
std::pair<bool, int> val2 = oh.get().as<std::pair<bool, int> >();
EXPECT_TRUE(val1.first == val2.first);
EXPECT_TRUE(val1.second == val2.second);
}
#if !defined(MSGPACK_USE_CPP03)
#include <boost/fusion/include/std_tuple.hpp>
TEST(MSGPACK_BOOST, fusion_pack_unpack_convert_tuple)
{
std::stringstream ss;
std::tuple<bool, int> val1(false, 42);
msgpack::pack(ss, val1);
msgpack::object_handle oh =
msgpack::unpack(ss.str().data(), ss.str().size());
std::tuple<bool, int> val2 = oh.get().as<std::tuple<bool, int> >();
EXPECT_TRUE(val1 == val2);
}
#endif // !defined(MSGPACK_USE_CPP03)
#endif // defined(MSGPACK_USE_BOOST) #endif // defined(MSGPACK_USE_BOOST)