Skip to content

Commit

Permalink
value_to supports TupleLike types
Browse files Browse the repository at this point in the history
  • Loading branch information
grisumbras committed Apr 25, 2021
1 parent 67e1c4d commit 3cbb737
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Boost 1.77.0:

* `value_to` supports `TupleLike` types.
* `object` deallocates the correct size.

Boost 1.76.0:
Expand Down
2 changes: 2 additions & 0 deletions doc/qbk/03_06_conversion.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ if `std::is_arithmetic<T>::value` is `true`, or

* `T` satisfies ['StringLike], or

* `T` satisfies ['TupleLike], or

* `T` satisfies ['ToMapLike], or

* `T` satisfies ['ToContainerLike].
Expand Down
5 changes: 5 additions & 0 deletions doc/qbk/release_notes.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
44 changes: 44 additions & 0 deletions include/boost/json/detail/index_sequence.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright (c) 2021 Dmitry Arkhipov ([email protected])
//
// 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 <boost/json/detail/config.hpp>
#ifndef BOOST_JSON_STANDALONE
# include <boost/mp11/integer_sequence.hpp>
#else
# include <type_traits>
#endif

BOOST_JSON_NS_BEGIN
namespace detail {

#if ! defined(BOOST_JSON_STANDALONE)

template <std::size_t... Is>
using index_sequence = boost::mp11::index_sequence<Is...>;

template <std::size_t N>
using make_index_sequence = boost::mp11::make_index_sequence<N>;

#else

template <std::size_t... Is>
using index_sequence = std::index_sequence<Is...>;

template <std::size_t N>
using make_index_sequence = std::make_index_sequence<N>;

#endif

} // detail
BOOST_JSON_NS_END

#endif // BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP
33 changes: 31 additions & 2 deletions include/boost/json/detail/value_to.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//
// Copyright (c) 2019 Vinnie Falco ([email protected])
// Copyright (c) 2020 Krystian Stasiowski ([email protected])
// Copyright (c) 2021 Dmitry Arkhipov ([email protected])
//
// 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)
Expand All @@ -12,6 +13,7 @@
#define BOOST_JSON_DETAIL_VALUE_TO_HPP

#include <boost/json/value.hpp>
#include <boost/json/detail/index_sequence.hpp>
#include <boost/json/detail/value_traits.hpp>

#include <type_traits>
Expand Down Expand Up @@ -110,12 +112,39 @@ template<class T, typename std::enable_if<
T
value_to_generic(
const value& jv,
priority_tag<2>)
priority_tag<3>)
{
auto& str = jv.as_string();
return T(str.data(), str.size());
}

template <class T, std::size_t... Is>
T
make_tuple_like(const array& arr, index_sequence<Is...>)
{
return T(value_to<typename std::tuple_element<Is, T>::type>(arr[Is])...);
}

// tuple-like types
template<class T, typename std::enable_if<
(std::tuple_size<remove_cvref<T>>::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<remove_cvref<T>>::value;
if ( N != arr.size() )
{
detail::throw_invalid_argument(
"array size does not match tuple size",
BOOST_JSON_SOURCE_POS);
}

return make_tuple_like<T>(arr, make_index_sequence<N>());
}

// map like containers
template<class T, typename std::enable_if<
has_value_to<typename map_traits<T>::pair_value_type>::value &&
Expand Down Expand Up @@ -170,7 +199,7 @@ tag_invoke(
value const& jv)
{
return value_to_generic<T>(
jv, priority_tag<2>());
jv, priority_tag<3>());
}

//----------------------------------------------------------
Expand Down
12 changes: 11 additions & 1 deletion test/value_to.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ BOOST_JSON_NS_BEGIN
class value_to_test
{
public:

template<class T>
void
check(T t)
Expand Down Expand Up @@ -66,6 +66,16 @@ class value_to_test
{ "a", 1 }, {"b", 2}, {"c", 3}
});
check(std::vector<int>{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<std::tuple<int, int>>(value{1, 2, 3})),
std::invalid_argument);
BOOST_TEST_THROWS(
(value_to<std::tuple<int, int, int, int>>(value{1, 2, 3})),
std::invalid_argument);
}

void
Expand Down

0 comments on commit 3cbb737

Please sign in to comment.