]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // |
2 | // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com) | |
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_VALUE_TRAITS_HPP | |
11 | #define BOOST_JSON_DETAIL_VALUE_TRAITS_HPP | |
12 | ||
13 | #include <boost/json/detail/config.hpp> | |
14 | #include <type_traits> | |
20effc67 TL |
15 | #include <utility> |
16 | ||
17 | BOOST_JSON_NS_BEGIN | |
18 | namespace detail { | |
19 | ||
20 | template<std::size_t N> | |
21 | struct priority_tag | |
22 | : priority_tag<N - 1> { }; | |
23 | ||
24 | template<> | |
25 | struct priority_tag<0> { }; | |
26 | ||
27 | using std::begin; | |
28 | using std::end; | |
29 | #ifdef __cpp_lib_nonmember_container_access | |
30 | using std::size; | |
31 | #endif | |
32 | ||
33 | template<typename T, typename = void> | |
34 | struct container_traits | |
35 | { | |
36 | static constexpr bool is_container = false; | |
37 | }; | |
38 | ||
39 | template<typename T> | |
40 | struct container_traits<T, typename std::enable_if< | |
41 | std::is_same<decltype(begin(std::declval<T&>())), | |
42 | decltype(end(std::declval<T&>()))>::value>::type> | |
43 | { | |
44 | private: | |
45 | template<typename U, typename std::enable_if< | |
46 | std::is_convertible<decltype(std::declval<U&>().size()), | |
47 | std::size_t>::value>::type* = nullptr> | |
48 | static | |
49 | std::size_t | |
50 | size_impl( | |
51 | U&& cont, | |
52 | priority_tag<2>) | |
53 | { | |
54 | return cont.size(); | |
55 | } | |
56 | ||
57 | template<typename U, typename std::enable_if< | |
58 | std::is_convertible<decltype(size(std::declval<U&>())), | |
59 | std::size_t>::value>::type* = nullptr> | |
60 | static | |
61 | std::size_t | |
62 | size_impl( | |
63 | U& cont, | |
64 | priority_tag<1>) | |
65 | { | |
66 | return size(cont); | |
67 | } | |
68 | ||
69 | template<typename U, std::size_t N> | |
70 | static | |
71 | std::size_t | |
72 | size_impl( | |
73 | U(&)[N], | |
74 | priority_tag<1>) | |
75 | { | |
76 | return N; | |
77 | } | |
78 | ||
79 | template<typename U> | |
80 | static | |
81 | std::size_t | |
82 | size_impl(U&, priority_tag<0>) | |
83 | { | |
84 | return 0; | |
85 | } | |
86 | ||
20effc67 TL |
87 | public: |
88 | static constexpr bool is_container = true; | |
89 | using value_type = remove_cvref< | |
90 | decltype(*begin(std::declval<T&>()))>; | |
91 | ||
92 | template<typename U> | |
93 | static | |
94 | std::size_t | |
95 | try_size(U& cont) | |
96 | { | |
97 | return container_traits::size_impl( | |
98 | cont, priority_tag<2>()); | |
99 | } | |
20effc67 TL |
100 | }; |
101 | ||
102 | template<typename T, typename = void> | |
103 | struct map_traits | |
104 | { | |
105 | static constexpr bool is_map = false; | |
106 | static constexpr bool has_unique_keys = false; | |
107 | }; | |
108 | ||
109 | template<typename T> | |
110 | struct map_traits<T, void_t<typename remove_cvref<T>::key_type, | |
111 | typename std::enable_if<container_traits<T>::is_container && | |
112 | std::tuple_size<typename remove_cvref<T>:: | |
113 | value_type>::value == 2>::type>> | |
114 | { | |
115 | private: | |
116 | template<typename U, typename = void> | |
117 | struct unique_keys : std::false_type { }; | |
118 | ||
119 | template<typename U> | |
120 | struct unique_keys<U, typename std::enable_if< | |
121 | (std::tuple_size<remove_cvref<decltype(std::declval< | |
1e59de90 | 122 | remove_cvref<U>&>().emplace(std::declval<typename |
20effc67 TL |
123 | remove_cvref<U>::value_type>()))>>::value > 0)>::type> |
124 | : std::true_type { }; | |
125 | public: | |
126 | static constexpr bool is_map = true; | |
127 | static constexpr bool has_unique_keys = unique_keys<T>::value; | |
128 | using pair_key_type = typename std::tuple_element< | |
129 | 0, typename remove_cvref<T>::value_type>::type; | |
130 | using pair_value_type = typename std::tuple_element< | |
131 | 1, typename remove_cvref<T>::value_type>::type; | |
132 | static constexpr bool key_converts_to_string = | |
133 | std::is_convertible<pair_key_type, string_view>::value; | |
134 | }; | |
135 | ||
136 | // does not include std::nullptr_t | |
137 | template<class T> | |
138 | using value_constructible = std::integral_constant<bool, | |
1e59de90 | 139 | std::is_same<detail::remove_cvref<T>, value>::value || |
20effc67 TL |
140 | std::is_same<detail::remove_cvref<T>, object>::value || |
141 | std::is_same<detail::remove_cvref<T>, array>::value || | |
142 | std::is_same<detail::remove_cvref<T>, string>::value || | |
143 | std::is_same<detail::remove_cvref<T>, string_view>::value || | |
1e59de90 TL |
144 | std::is_arithmetic<detail::remove_cvref<T>>::value || |
145 | std::is_same<detail::remove_cvref<T>, char const*>::value || | |
146 | std::is_same<detail::remove_cvref<T>, | |
20effc67 TL |
147 | std::initializer_list<value_ref>>::value || |
148 | std::is_same<detail::remove_cvref<T>, value_ref>::value>; | |
149 | ||
150 | BOOST_STATIC_ASSERT(value_constructible<value>::value); | |
151 | ||
152 | } // detail | |
153 | BOOST_JSON_NS_END | |
154 | ||
155 | #endif |