@@ -26,6 +26,15 @@ namespace detail
2626// helpers //
2727// ///////////
2828
29+ // Note to maintainers:
30+ //
31+ // Every trait in this file expects a non CV-qualified type.
32+ // The only exceptions are in the 'aliases for detected' section
33+ // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
34+ //
35+ // In this case, T has to be properly CV-qualified to constraint the function arguments
36+ // (e.g. to_json(BasicJsonType&, const T&))
37+
2938template <typename > struct is_basic_json : std::false_type {};
3039
3140NLOHMANN_BASIC_JSON_TPL_DECLARATION
@@ -68,6 +77,52 @@ using from_json_function = decltype(T::from_json(std::declval<Args>()...));
6877template <typename T, typename U>
6978using get_template_function = decltype (std::declval<T>().template get<U>());
7079
80+ // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
81+ template <typename BasicJsonType, typename T, typename = void >
82+ struct has_from_json : std::false_type {};
83+
84+ template <typename BasicJsonType, typename T>
85+ struct has_from_json <BasicJsonType, T,
86+ enable_if_t <not is_basic_json<T>::value>>
87+ {
88+ using serializer = typename BasicJsonType::template json_serializer<T, void >;
89+
90+ static constexpr bool value =
91+ is_detected_exact<void , from_json_function, serializer,
92+ const BasicJsonType&, T&>::value;
93+ };
94+
95+ // This trait checks if JSONSerializer<T>::from_json(json const&) exists
96+ // this overload is used for non-default-constructible user-defined-types
97+ template <typename BasicJsonType, typename T, typename = void >
98+ struct has_non_default_from_json : std::false_type {};
99+
100+ template <typename BasicJsonType, typename T>
101+ struct has_non_default_from_json <BasicJsonType, T, enable_if_t <not is_basic_json<T>::value>>
102+ {
103+ using serializer = typename BasicJsonType::template json_serializer<T, void >;
104+
105+ static constexpr bool value =
106+ is_detected_exact<T, from_json_function, serializer,
107+ const BasicJsonType&>::value;
108+ };
109+
110+ // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
111+ // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
112+ template <typename BasicJsonType, typename T, typename = void >
113+ struct has_to_json : std::false_type {};
114+
115+ template <typename BasicJsonType, typename T>
116+ struct has_to_json <BasicJsonType, T, enable_if_t <not is_basic_json<T>::value>>
117+ {
118+ using serializer = typename BasicJsonType::template json_serializer<T, void >;
119+
120+ static constexpr bool value =
121+ is_detected_exact<void , to_json_function, serializer, BasicJsonType&,
122+ T>::value;
123+ };
124+
125+
71126// /////////////////
72127// is_ functions //
73128// /////////////////
@@ -123,6 +178,35 @@ template <typename BasicJsonType, typename CompatibleObjectType>
123178struct is_compatible_object_type
124179 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
125180
181+ template <typename BasicJsonType, typename ConstructibleObjectType,
182+ typename = void >
183+ struct is_constructible_object_type_impl : std::false_type {};
184+
185+ template <typename BasicJsonType, typename ConstructibleObjectType>
186+ struct is_constructible_object_type_impl <
187+ BasicJsonType, ConstructibleObjectType,
188+ enable_if_t <is_detected<mapped_type_t , ConstructibleObjectType>::value and
189+ is_detected<key_type_t , ConstructibleObjectType>::value >>
190+ {
191+ using object_t = typename BasicJsonType::object_t ;
192+
193+ static constexpr bool value =
194+ std::is_constructible<typename ConstructibleObjectType::key_type,
195+ typename object_t ::key_type>::value and
196+ std::is_same<typename object_t ::mapped_type,
197+ typename ConstructibleObjectType::mapped_type>::value or
198+ (has_from_json<BasicJsonType,
199+ typename ConstructibleObjectType::mapped_type>::value or
200+ has_non_default_from_json <
201+ BasicJsonType,
202+ typename ConstructibleObjectType::mapped_type >::value);
203+ };
204+
205+ template <typename BasicJsonType, typename ConstructibleObjectType>
206+ struct is_constructible_object_type
207+ : is_constructible_object_type_impl<BasicJsonType,
208+ ConstructibleObjectType> {};
209+
126210template <typename BasicJsonType, typename CompatibleStringType,
127211 typename = void >
128212struct is_compatible_string_type_impl : std::false_type {};
@@ -137,9 +221,28 @@ struct is_compatible_string_type_impl <
137221 std::is_constructible<typename BasicJsonType::string_t , CompatibleStringType>::value;
138222};
139223
140- template <typename BasicJsonType, typename CompatibleStringType >
224+ template <typename BasicJsonType, typename ConstrutibleStringType >
141225struct is_compatible_string_type
142- : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
226+ : is_compatible_string_type_impl<BasicJsonType, ConstrutibleStringType> {};
227+
228+ template <typename BasicJsonType, typename ConstrutibleStringType,
229+ typename = void >
230+ struct is_constructible_string_type_impl : std::false_type {};
231+
232+ template <typename BasicJsonType, typename ConstrutibleStringType>
233+ struct is_constructible_string_type_impl <
234+ BasicJsonType, ConstrutibleStringType,
235+ enable_if_t <is_detected_exact<typename BasicJsonType::string_t ::value_type,
236+ value_type_t , ConstrutibleStringType>::value >>
237+ {
238+ static constexpr auto value =
239+ std::is_constructible<ConstrutibleStringType,
240+ typename BasicJsonType::string_t >::value;
241+ };
242+
243+ template <typename BasicJsonType, typename ConstrutibleStringType>
244+ struct is_constructible_string_type
245+ : is_constructible_string_type_impl<BasicJsonType, ConstrutibleStringType> {};
143246
144247template <typename BasicJsonType, typename CompatibleArrayType, typename = void >
145248struct is_compatible_array_type_impl : std::false_type {};
@@ -148,18 +251,61 @@ template <typename BasicJsonType, typename CompatibleArrayType>
148251struct is_compatible_array_type_impl <
149252 BasicJsonType, CompatibleArrayType,
150253 enable_if_t <is_detected<value_type_t , CompatibleArrayType>::value and
151- is_detected<iterator_t , CompatibleArrayType>::value >>
254+ is_detected<iterator_t , CompatibleArrayType>::value and
255+ // This is needed because json_reverse_iterator has a ::iterator type...
256+ // Therefore it is detected as a CompatibleArrayType.
257+ // The real fix would be to have an Iterable concept.
258+ not is_iterator_traits<
259+ std::iterator_traits<CompatibleArrayType>>::value >>
152260{
153- // This is needed because json_reverse_iterator has a ::iterator type...
154- // Therefore it is detected as a CompatibleArrayType.
155- // The real fix would be to have an Iterable concept.
156- static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
261+ static constexpr bool value =
262+ std::is_constructible<BasicJsonType,
263+ typename CompatibleArrayType::value_type>::value;
157264};
158265
159266template <typename BasicJsonType, typename CompatibleArrayType>
160267struct is_compatible_array_type
161268 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
162269
270+ template <typename BasicJsonType, typename ConstructibleArrayType, typename = void >
271+ struct is_constructible_array_type_impl : std::false_type {};
272+
273+ template <typename BasicJsonType, typename ConstructibleArrayType>
274+ struct is_constructible_array_type_impl <
275+ BasicJsonType, ConstructibleArrayType,
276+ enable_if_t <std::is_same<ConstructibleArrayType,
277+ typename BasicJsonType::value_type>::value >>
278+ : std::true_type {};
279+
280+ template <typename BasicJsonType, typename ConstructibleArrayType>
281+ struct is_constructible_array_type_impl <
282+ BasicJsonType, ConstructibleArrayType,
283+ enable_if_t <not std::is_same<ConstructibleArrayType,
284+ typename BasicJsonType::value_type>::value and
285+ is_detected<value_type_t , ConstructibleArrayType>::value and
286+ is_detected<iterator_t , ConstructibleArrayType>::value and
287+ is_complete_type<
288+ detected_t <value_type_t , ConstructibleArrayType>>::value >>
289+ {
290+ static constexpr bool value =
291+ // This is needed because json_reverse_iterator has a ::iterator type,
292+ // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
293+ // Therefore it is detected as a ConstructibleArrayType.
294+ // The real fix would be to have an Iterable concept.
295+ not is_iterator_traits <
296+ std::iterator_traits<ConstructibleArrayType >>::value and
297+
298+ (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t ::value_type>::value or
299+ has_from_json<BasicJsonType,
300+ typename ConstructibleArrayType::value_type>::value or
301+ has_non_default_from_json <
302+ BasicJsonType, typename ConstructibleArrayType::value_type >::value);
303+ };
304+
305+ template <typename BasicJsonType, typename ConstructibleArrayType>
306+ struct is_constructible_array_type
307+ : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
308+
163309template <typename RealIntegerType, typename CompatibleNumberIntegerType,
164310 typename = void >
165311struct is_compatible_integer_type_impl : std::false_type {};
@@ -187,51 +333,6 @@ struct is_compatible_integer_type
187333 : is_compatible_integer_type_impl<RealIntegerType,
188334 CompatibleNumberIntegerType> {};
189335
190- // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
191- template <typename BasicJsonType, typename T, typename = void >
192- struct has_from_json : std::false_type {};
193-
194- template <typename BasicJsonType, typename T>
195- struct has_from_json <BasicJsonType, T,
196- enable_if_t <not is_basic_json<T>::value>>
197- {
198- using serializer = typename BasicJsonType::template json_serializer<T, void >;
199-
200- static constexpr bool value =
201- is_detected_exact<void , from_json_function, serializer,
202- const BasicJsonType&, T&>::value;
203- };
204-
205- // This trait checks if JSONSerializer<T>::from_json(json const&) exists
206- // this overload is used for non-default-constructible user-defined-types
207- template <typename BasicJsonType, typename T, typename = void >
208- struct has_non_default_from_json : std::false_type {};
209-
210- template <typename BasicJsonType, typename T>
211- struct has_non_default_from_json <BasicJsonType, T, enable_if_t <not is_basic_json<T>::value>>
212- {
213- using serializer = typename BasicJsonType::template json_serializer<T, void >;
214-
215- static constexpr bool value =
216- is_detected_exact<T, from_json_function, serializer,
217- const BasicJsonType&>::value;
218- };
219-
220- // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
221- // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
222- template <typename BasicJsonType, typename T, typename = void >
223- struct has_to_json : std::false_type {};
224-
225- template <typename BasicJsonType, typename T>
226- struct has_to_json <BasicJsonType, T, enable_if_t <not is_basic_json<T>::value>>
227- {
228- using serializer = typename BasicJsonType::template json_serializer<T, void >;
229-
230- static constexpr bool value =
231- is_detected_exact<void , to_json_function, serializer, BasicJsonType&,
232- T>::value;
233- };
234-
235336template <typename BasicJsonType, typename CompatibleType, typename = void >
236337struct is_compatible_type_impl : std::false_type {};
237338
0 commit comments