diff --git a/cpp11/tuple.hpp b/cpp11/tuple.hpp index 1a92e208..30f9f54f 100644 --- a/cpp11/tuple.hpp +++ b/cpp11/tuple.hpp @@ -18,11 +18,92 @@ #ifndef MSGPACK_TYPE_TUPLE_HPP #define MSGPACK_TYPE_TUPLE_HPP +#include + #include "msgpack/object.hpp" #include "msgpack/cpp_config.hpp" namespace msgpack { +namespace type { + // tuple + using std::get; + using std::tuple_size; + using std::tuple_element; + using std::uses_allocator; + using std::ignore; + + template< class... Types > + class tuple : public std::tuple { + public: + using std::tuple::tuple; + + template< std::size_t I> + typename tuple_element >::type& + get() { return std::get(*this); } + + template< std::size_t I> + typename tuple_element >::type const& + get() const { return std::get(*this); } + + template< std::size_t I> + typename tuple_element >::type&& + get() && { return std::get(*this); } + }; + + template< class... Types > + tuple make_tuple( Types&&... args ) { + return tuple(std::forward(args)...); + } + + template< class... Types > + tuple make_tuple( std::tuple&& arg ) { + return tuple(std::forward&&>(arg)); + } + + template< class... Types > + tuple tie( Types&... args ) { + return std::tie(args...); + } + + template< class... Types > + tuple forward_as_tuple( Types&&... args ) { + return std::forward_as_tuple(std::forward(args)...); + } + + namespace detail { + template < typename... Types > + std::tuple&& get_std_tuple(tuple&& t) { + return std::forward&&>(t); + } + template < typename... Types > + std::tuple& get_std_tuple(tuple& t) { + return t; + } + template < typename... Types > + std::tuple const& get_std_tuple(tuple const& t) { + return t; + } + template < typename T > + T&& get_std_tuple(T&& t) { + return t; + } + } + template< class... Tuples > + auto tuple_cat(Tuples&&... args) -> + decltype( + msgpack::type::make_tuple(std::tuple_cat(detail::get_std_tuple(std::forward(args))...)) + ) { + return std::tuple_cat(detail::get_std_tuple(std::forward(args))...); + } + + template< class... Types > + void swap( tuple& lhs, tuple& rhs ) { + lhs.swap(rhs); + } + +} // namespace type + // --- Pack ( from tuple to packer stream --- template struct Packer { diff --git a/src/msgpack/cpp_config.hpp b/src/msgpack/cpp_config.hpp index 9c1dbb0c..b80573a5 100644 --- a/src/msgpack/cpp_config.hpp +++ b/src/msgpack/cpp_config.hpp @@ -63,19 +63,6 @@ namespace msgpack { using std::move; using std::swap; - namespace type { - // tuple - using std::tuple; - using std::get; - using std::make_tuple; - using std::tie; - using std::forward_as_tuple; - using std::tuple_cat; - using std::tuple_size; - using std::tuple_element; - using std::uses_allocator; - using std::ignore; - } } // msgpack diff --git a/test/Makefile.am b/test/Makefile.am index 1939f25c..08efc428 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -16,6 +16,7 @@ check_PROGRAMS = \ fixint \ fixint_c \ version \ + msgpack_tuple \ msgpackc_test \ msgpack_test @@ -46,6 +47,8 @@ fixint_c_SOURCES = fixint_c.cc version_SOURCES = version.cc +msgpack_tuple_SOURCES = msgpack_tuple.cc + msgpackc_test_SOURCES = msgpackc_test.cpp msgpack_test_SOURCES = msgpack_test.cpp diff --git a/test/msgpack_tuple.cc b/test/msgpack_tuple.cc new file mode 100644 index 00000000..57364f97 --- /dev/null +++ b/test/msgpack_tuple.cc @@ -0,0 +1,106 @@ +#include +#include + + +TEST(msgpack_tuple, member_get) +{ + msgpack::type::tuple t1(42, true, "ABC"); + EXPECT_EQ(42, t1.get<0>()); + EXPECT_EQ(true, t1.get<1>()); + EXPECT_EQ("ABC", t1.get<2>()); + t1.get<0>() = 40; + t1.get<1>() = false; + t1.get<2>() = "DEFG"; + EXPECT_EQ(40, t1.get<0>()); + EXPECT_EQ(false, t1.get<1>()); + EXPECT_EQ("DEFG", t1.get<2>()); +} + +TEST(msgpack_tuple, non_member_get) +{ + msgpack::type::tuple t1(42, true, "ABC"); + EXPECT_EQ(42, msgpack::type::get<0>(t1)); + EXPECT_EQ(true, msgpack::type::get<1>(t1)); + EXPECT_EQ("ABC", msgpack::type::get<2>(t1)); + msgpack::type::get<0>(t1) = 40; + msgpack::type::get<1>(t1) = false; + msgpack::type::get<2>(t1) = "DEFG"; + EXPECT_EQ(40, msgpack::type::get<0>(t1)); + EXPECT_EQ(false, msgpack::type::get<1>(t1)); + EXPECT_EQ("DEFG", msgpack::type::get<2>(t1)); +} + +TEST(msgpack_tuple, std_non_member_get) +{ + msgpack::type::tuple t1(42, true, "ABC"); + EXPECT_EQ(42, std::get<0>(t1)); + EXPECT_EQ(true, std::get<1>(t1)); + EXPECT_EQ("ABC", std::get<2>(t1)); + std::get<0>(t1) = 40; + std::get<1>(t1) = false; + std::get<2>(t1) = "DEFG"; + EXPECT_EQ(40, std::get<0>(t1)); + EXPECT_EQ(false, std::get<1>(t1)); + EXPECT_EQ("DEFG", std::get<2>(t1)); +} + +TEST(msgpack_tuple, make_tuple) +{ + msgpack::type::tuple t1 = msgpack::type::make_tuple(42, true, "ABC"); + EXPECT_EQ(42, t1.get<0>()); + EXPECT_EQ(true, t1.get<1>()); + EXPECT_EQ("ABC", t1.get<2>()); + t1.get<0>() = 40; + t1.get<1>() = false; + t1.get<2>() = "DEFG"; + EXPECT_EQ(40, t1.get<0>()); + EXPECT_EQ(false, t1.get<1>()); + EXPECT_EQ("DEFG", t1.get<2>()); + + msgpack::type::tuple t2 = + msgpack::type::make_tuple(std::make_tuple(42, true, "ABC")); + EXPECT_EQ(42, t2.get<0>()); + EXPECT_EQ(true, t2.get<1>()); + EXPECT_EQ("ABC", t2.get<2>()); + +} + +TEST(msgpack_tuple, tie) +{ + int i(42); + bool b(true); + std::string s("ABC"); + msgpack::type::tuple t1 = msgpack::type::tie(i, b, s); + EXPECT_EQ(42, t1.get<0>()); + EXPECT_EQ(true, t1.get<1>()); + EXPECT_EQ("ABC", t1.get<2>()); + t1.get<0>() = 40; + t1.get<1>() = false; + t1.get<2>() = "DEFG"; + EXPECT_EQ(40, t1.get<0>()); + EXPECT_EQ(false, t1.get<1>()); + EXPECT_EQ("DEFG", t1.get<2>()); +} + +TEST(msgpack_tuple, tuple_cat) +{ + msgpack::type::tuple t1 = msgpack::type::make_tuple(42); + msgpack::type::tuple t2 = msgpack::type::make_tuple(true, "ABC"); + msgpack::type::tuple t3 = msgpack::type::tuple_cat(t1, std::move(t2)); + EXPECT_EQ(42, t3.get<0>()); + EXPECT_EQ(true, t3.get<1>()); + EXPECT_EQ("ABC", t3.get<2>()); +} + +TEST(msgpack_tuple, swap) +{ + msgpack::type::tuple t1 = msgpack::type::make_tuple(42, true, "ABC"); + msgpack::type::tuple t2 = msgpack::type::make_tuple(40, false, "DEFG"); + msgpack::type::swap(t1, t2); + EXPECT_EQ(42, t2.get<0>()); + EXPECT_EQ(true, t2.get<1>()); + EXPECT_EQ("ABC", t2.get<2>()); + EXPECT_EQ(40, t1.get<0>()); + EXPECT_EQ(false, t1.get<1>()); + EXPECT_EQ("DEFG", t1.get<2>()); +}