From 3cbb7370cd04dc0778e4e095c1a11dcfbe159328 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Wed, 3 Mar 2021 10:15:04 +0300 Subject: [PATCH] value_to supports TupleLike types --- CHANGELOG.md | 1 + doc/qbk/03_06_conversion.qbk | 2 + doc/qbk/release_notes.qbk | 5 +++ include/boost/json/detail/index_sequence.hpp | 44 ++++++++++++++++++++ include/boost/json/detail/value_to.hpp | 33 ++++++++++++++- test/value_to.cpp | 12 +++++- 6 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 include/boost/json/detail/index_sequence.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 820a32b21..35a1fbff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ Boost 1.77.0: +* `value_to` supports `TupleLike` types. * `object` deallocates the correct size. Boost 1.76.0: diff --git a/doc/qbk/03_06_conversion.qbk b/doc/qbk/03_06_conversion.qbk index 1870aee4f..cfabb7f3b 100644 --- a/doc/qbk/03_06_conversion.qbk +++ b/doc/qbk/03_06_conversion.qbk @@ -189,6 +189,8 @@ if `std::is_arithmetic::value` is `true`, or * `T` satisfies ['StringLike], or +* `T` satisfies ['TupleLike], or + * `T` satisfies ['ToMapLike], or * `T` satisfies ['ToContainerLike]. diff --git a/doc/qbk/release_notes.qbk b/doc/qbk/release_notes.qbk index 1394c86ba..06b8ef3bd 100644 --- a/doc/qbk/release_notes.qbk +++ b/doc/qbk/release_notes.qbk @@ -13,10 +13,15 @@ [heading Boost 1.77.0] + [*Fixes] * __object__ deallocates the correct size. +[*Improvements] + +* __value_to__ supports `TupleLike` types. + [heading Boost 1.76.0] [*Fixes] diff --git a/include/boost/json/detail/index_sequence.hpp b/include/boost/json/detail/index_sequence.hpp new file mode 100644 index 000000000..55df00c26 --- /dev/null +++ b/include/boost/json/detail/index_sequence.hpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/json +// + +#ifndef BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP +#define BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP + +#include +#ifndef BOOST_JSON_STANDALONE +# include +#else +# include +#endif + +BOOST_JSON_NS_BEGIN +namespace detail { + +#if ! defined(BOOST_JSON_STANDALONE) + +template +using index_sequence = boost::mp11::index_sequence; + +template +using make_index_sequence = boost::mp11::make_index_sequence; + +#else + +template +using index_sequence = std::index_sequence; + +template +using make_index_sequence = std::make_index_sequence; + +#endif + +} // detail +BOOST_JSON_NS_END + +#endif // BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP diff --git a/include/boost/json/detail/value_to.hpp b/include/boost/json/detail/value_to.hpp index ba842c1c8..df9f6dba0 100644 --- a/include/boost/json/detail/value_to.hpp +++ b/include/boost/json/detail/value_to.hpp @@ -1,6 +1,7 @@ // // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) +// Copyright (c) 2021 Dmitry Arkhipov (grisumbras@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,6 +13,7 @@ #define BOOST_JSON_DETAIL_VALUE_TO_HPP #include +#include #include #include @@ -110,12 +112,39 @@ template) + priority_tag<3>) { auto& str = jv.as_string(); return T(str.data(), str.size()); } +template +T +make_tuple_like(const array& arr, index_sequence) +{ + return T(value_to::type>(arr[Is])...); +} + +// tuple-like types +template>::value > 0)>::type* = nullptr> +T +value_to_generic( + const value& jv, + priority_tag<2>) +{ + auto& arr = jv.as_array(); + constexpr std::size_t N = std::tuple_size>::value; + if ( N != arr.size() ) + { + detail::throw_invalid_argument( + "array size does not match tuple size", + BOOST_JSON_SOURCE_POS); + } + + return make_tuple_like(arr, make_index_sequence()); +} + // map like containers template::pair_value_type>::value && @@ -170,7 +199,7 @@ tag_invoke( value const& jv) { return value_to_generic( - jv, priority_tag<2>()); + jv, priority_tag<3>()); } //---------------------------------------------------------- diff --git a/test/value_to.cpp b/test/value_to.cpp index e1ee5faeb..8b6c9a67a 100644 --- a/test/value_to.cpp +++ b/test/value_to.cpp @@ -21,7 +21,7 @@ BOOST_JSON_NS_BEGIN class value_to_test { public: - + template void check(T t) @@ -66,6 +66,16 @@ class value_to_test { "a", 1 }, {"b", 2}, {"c", 3} }); check(std::vector{1, 2, 3, 4}); + check(std::make_pair(std::string("test"), 5)); + check(std::make_tuple(std::string("outer"), + std::make_pair(std::string("test"), 5))); + + BOOST_TEST_THROWS( + (value_to>(value{1, 2, 3})), + std::invalid_argument); + BOOST_TEST_THROWS( + (value_to>(value{1, 2, 3})), + std::invalid_argument); } void