Skip to content

Commit aae1863

Browse files
committed
value_to supports TupleLike types
1 parent ae6ca2a commit aae1863

File tree

6 files changed

+97
-3
lines changed

6 files changed

+97
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Boost 1.77.0:
22

33
* Implicit conversion operator from `string` to `std::string_view`.
4+
* `value_to` supports `TupleLike` types.
45
* `object` deallocates the correct size.
56

67
Boost 1.76.0:

doc/qbk/03_06_conversion.qbk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ if `std::is_arithmetic<T>::value` is `true`, or
189189

190190
* `T` satisfies ['StringLike], or
191191

192+
* `T` satisfies ['TupleLike], or
193+
192194
* `T` satisfies ['ToMapLike], or
193195

194196
* `T` satisfies ['ToContainerLike].

doc/qbk/release_notes.qbk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
* __object__ deallocates the correct size.
2424

25+
[*Improvements]
26+
27+
* __value_to__ supports `TupleLike` types.
28+
2529
[heading Boost 1.76.0]
2630

2731
[*Fixes]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// Copyright (c) 2021 Dmitry Arkhipov ([email protected])
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
//
7+
// Official repository: https://github.com/boostorg/json
8+
//
9+
10+
#ifndef BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP
11+
#define BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP
12+
13+
#include <boost/json/detail/config.hpp>
14+
#ifndef BOOST_JSON_STANDALONE
15+
# include <boost/mp11/integer_sequence.hpp>
16+
#else
17+
# include <type_traits>
18+
#endif
19+
20+
BOOST_JSON_NS_BEGIN
21+
namespace detail {
22+
23+
#if ! defined(BOOST_JSON_STANDALONE)
24+
25+
template <std::size_t... Is>
26+
using index_sequence = boost::mp11::index_sequence<Is...>;
27+
28+
template <std::size_t N>
29+
using make_index_sequence = boost::mp11::make_index_sequence<N>;
30+
31+
#else
32+
33+
template <std::size_t... Is>
34+
using index_sequence = std::index_sequence<Is...>;
35+
36+
template <std::size_t N>
37+
using make_index_sequence = std::make_index_sequence<N>;
38+
39+
#endif
40+
41+
} // detail
42+
BOOST_JSON_NS_END
43+
44+
#endif // BOOST_JSON_DETAIL_INDEX_SEQUENCE_HPP

include/boost/json/detail/value_to.hpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//
22
// Copyright (c) 2019 Vinnie Falco ([email protected])
33
// Copyright (c) 2020 Krystian Stasiowski ([email protected])
4+
// Copyright (c) 2021 Dmitry Arkhipov ([email protected])
45
//
56
// Distributed under the Boost Software License, Version 1.0. (See accompanying
67
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -12,6 +13,7 @@
1213
#define BOOST_JSON_DETAIL_VALUE_TO_HPP
1314

1415
#include <boost/json/value.hpp>
16+
#include <boost/json/detail/index_sequence.hpp>
1517
#include <boost/json/detail/value_traits.hpp>
1618

1719
#include <type_traits>
@@ -110,12 +112,39 @@ template<class T, typename std::enable_if<
110112
T
111113
value_to_generic(
112114
const value& jv,
113-
priority_tag<2>)
115+
priority_tag<3>)
114116
{
115117
auto& str = jv.as_string();
116118
return T(str.data(), str.size());
117119
}
118120

121+
template <class T, std::size_t... Is>
122+
T
123+
make_tuple_like(const array& arr, index_sequence<Is...>)
124+
{
125+
return T(value_to<typename std::tuple_element<Is, T>::type>(arr[Is])...);
126+
}
127+
128+
// tuple-like types
129+
template<class T, typename std::enable_if<
130+
(std::tuple_size<remove_cvref<T>>::value > 0)>::type* = nullptr>
131+
T
132+
value_to_generic(
133+
const value& jv,
134+
priority_tag<2>)
135+
{
136+
auto& arr = jv.as_array();
137+
constexpr std::size_t N = std::tuple_size<remove_cvref<T>>::value;
138+
if ( N != arr.size() )
139+
{
140+
detail::throw_invalid_argument(
141+
"array size does not match tuple size",
142+
BOOST_JSON_SOURCE_POS);
143+
}
144+
145+
return make_tuple_like<T>(arr, make_index_sequence<N>());
146+
}
147+
119148
// map like containers
120149
template<class T, typename std::enable_if<
121150
has_value_to<typename map_traits<T>::pair_value_type>::value &&
@@ -170,7 +199,7 @@ tag_invoke(
170199
value const& jv)
171200
{
172201
return value_to_generic<T>(
173-
jv, priority_tag<2>());
202+
jv, priority_tag<3>());
174203
}
175204

176205
//----------------------------------------------------------

test/value_to.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ BOOST_JSON_NS_BEGIN
2121
class value_to_test
2222
{
2323
public:
24-
24+
2525
template<class T>
2626
void
2727
check(T t)
@@ -66,6 +66,20 @@ class value_to_test
6666
{ "a", 1 }, {"b", 2}, {"c", 3}
6767
});
6868
check(std::vector<int>{1, 2, 3, 4});
69+
check(std::make_pair(std::string("test"), 5));
70+
check(std::make_tuple(std::string("outer"),
71+
std::make_pair(std::string("test"), 5)));
72+
check(std::map<int, int>
73+
{
74+
{2, 4}, {3, 9}, {5, 25}
75+
});
76+
77+
BOOST_TEST_THROWS(
78+
(value_to<std::tuple<int, int>>(value{1, 2, 3})),
79+
std::invalid_argument);
80+
BOOST_TEST_THROWS(
81+
(value_to<std::tuple<int, int, int, int>>(value{1, 2, 3})),
82+
std::invalid_argument);
6983
}
7084

7185
void

0 commit comments

Comments
 (0)