53 namespace json_details {
56 number_parse_type_impl_test( ) {
57 if constexpr( daw::is_floating_point_v<T> ) {
58 return JsonParseTypes::Real;
59 }
else if constexpr( daw::is_signed_v<T> ) {
60 return JsonParseTypes::Signed;
62 static_assert( daw::is_unsigned_v<T> );
63 return JsonParseTypes::Unsigned;
68 DAW_ATTRIB_INLINE DAW_CONSTEVAL
JsonParseTypes number_parse_type_test( ) {
69 if constexpr( std::is_enum_v<T> ) {
70 return number_parse_type_impl_test<std::underlying_type_t<T>>( );
72 return number_parse_type_impl_test<T>( );
78 number_parse_type_test<T>( );
80 template<
typename,
typename AllowRawString,
typename =
void>
81 struct json_deduced_type_map {
82 static constexpr bool is_null =
false;
83 static constexpr auto parse_type = JsonParseTypes::Unknown;
85 static constexpr bool type_map_found =
false;
88 template<
typename JsonType,
typename AllowRawString>
90 struct json_deduced_type_map<
91 JsonType, AllowRawString DAW_ENABLEIF_S( is_a_json_type_v<JsonType> )> {
92 static constexpr bool is_null =
false;
93 static constexpr auto parse_type = JsonParseTypes::Unknown;
95 using type = JsonType;
96 static constexpr bool type_map_found =
true;
99 template<
typename T,
typename AllowRawString>
101 struct json_deduced_type_map<
102 T, AllowRawString DAW_ENABLEIF_S( has_json_data_contract_trait_v<T> )> {
103 static constexpr bool is_null =
false;
105 static_assert( is_json_member_list_v<type>,
106 "Expected a JSON member list" );
107 static constexpr auto parse_type = JsonParseTypes::Unknown;
109 static constexpr bool type_map_found =
true;
113 struct json_deduced_type_map<
daw::string_view, std::true_type> {
114 static constexpr bool is_null =
false;
115 static constexpr auto parse_type = JsonParseTypes::StringRaw;
117 static constexpr bool type_map_found =
true;
121 struct json_deduced_type_map<
daw::string_view, std::false_type> {
122 static constexpr bool is_null =
false;
123 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
125 static constexpr bool type_map_found =
true;
129 struct json_deduced_type_map<
std::string_view, std::true_type> {
130 static constexpr bool is_null =
false;
131 static constexpr auto parse_type = JsonParseTypes::StringRaw;
133 static constexpr bool type_map_found =
true;
137 struct json_deduced_type_map<
std::string_view, std::false_type> {
138 static constexpr bool is_null =
false;
139 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
141 static constexpr bool type_map_found =
true;
147 struct json_deduced_type_map<char,
std::false_type> {
148 static constexpr bool is_null =
false;
149 static constexpr auto parse_type = JsonParseTypes::StringInsitu;
151 static constexpr bool type_map_found =
true;
154 template<
typename AllowRawString>
155 struct json_deduced_type_map<
std::string, AllowRawString> {
156 static constexpr bool is_null =
false;
157 static constexpr auto parse_type = JsonParseTypes::StringEscaped;
159 static constexpr bool type_map_found =
true;
162 template<
typename AllowRawString>
163 struct json_deduced_type_map<bool, AllowRawString> {
164 static constexpr bool is_null =
false;
165 static constexpr auto parse_type = JsonParseTypes::Bool;
166 static constexpr bool type_map_found =
true;
171#if defined( _LIBCPP_VERSION )
172 template<
typename AllowRawString>
173 struct json_deduced_type_map<typename
std::vector<bool>::const_reference,
176 static constexpr bool is_null =
false;
177 static constexpr auto parse_type = JsonParseTypes::Bool;
179 static constexpr bool type_map_found =
true;
183 template<
typename Integer,
typename AllowRawString>
185 not json_details::has_json_data_contract_trait_v<Integer> and
186 daw::is_integral_v<Integer> )
187 struct json_deduced_type_map<
188 Integer, AllowRawString DAW_ENABLEIF_S(
189 not json_details::has_json_data_contract_trait_v<Integer> and
190 daw::is_integral_v<Integer> )> {
191 static constexpr bool is_null =
false;
192 static constexpr auto parse_type = daw::is_signed_v<Integer>
193 ? JsonParseTypes::Signed
194 : JsonParseTypes::Unsigned;
196 static constexpr bool type_map_found =
true;
199 template<
typename Enum,
typename AllowRawString>
200 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Enum> and
201 std::is_enum_v<Enum> )
202 struct json_deduced_type_map<
203 Enum, AllowRawString DAW_ENABLEIF_S(
204 not json_details::has_json_data_contract_trait_v<Enum> and
205 std::is_enum_v<Enum> )> {
206 static constexpr bool is_null =
false;
207 static constexpr auto parse_type =
208 daw::is_signed_v<std::underlying_type<Enum>>
209 ? JsonParseTypes::Signed
210 : JsonParseTypes::Unsigned;
212 static constexpr bool type_map_found =
true;
215 template<
typename FloatingPo
int,
typename AllowRawString>
217 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
218 daw::is_floating_point_v<FloatingPoint> )
219 struct json_deduced_type_map<
221 AllowRawString DAW_ENABLEIF_S(
222 not json_details::has_json_data_contract_trait_v<FloatingPoint> and
223 daw::is_floating_point_v<FloatingPoint> )> {
224 static constexpr bool is_null =
false;
225 static constexpr auto parse_type = JsonParseTypes::Real;
227 static constexpr bool type_map_found =
true;
230 template<
typename Tuple,
typename AllowRawString>
231 DAW_REQUIRES( not json_details::has_json_data_contract_trait_v<Tuple> and
233 struct json_deduced_type_map<
234 Tuple, AllowRawString DAW_ENABLEIF_S(
235 not json_details::has_json_data_contract_trait_v<Tuple> and
236 is_tuple_v<Tuple> )> {
237 static constexpr bool is_null =
false;
238 static constexpr auto parse_type = JsonParseTypes::Tuple;
240 static constexpr bool type_map_found =
true;
243 namespace container_detect {
245 using is_string_test =
246 decltype( (void)( std::begin( std::declval<T &>( ) ) ),
247 (
void)( std::end( std::declval<T &>( ) ) ),
248 std::declval<typename T::value_type>( ) );
251 template<
typename String>
252 DAW_CPP20_CONCEPT is_string_v = std::is_same_v<
253 char, daw::detected_t<container_detect::is_string_test, String>>;
256 is_associative_container_v,
257 ( (
void)( std::begin( std::declval<T &>( ) ) ),
258 (
void)( std::end( std::declval<T &>( ) ) ),
259 (
void)( std::declval<typename T::value_type>( ) ),
260 (
void)( std::declval<typename T::key_type>( ) ),
261 (
void)( std::declval<typename T::mapped_type>( ) ) ) );
263 template<
typename AssociativeContainer,
typename AllowRawString>
264 DAW_REQUIRES( not has_json_data_contract_trait_v<AssociativeContainer> and
265 is_associative_container_v<AssociativeContainer> )
266 struct json_deduced_type_map<
267 AssociativeContainer,
268 AllowRawString DAW_ENABLEIF_S(
269 not has_json_data_contract_trait_v<AssociativeContainer> and
270 is_associative_container_v<AssociativeContainer> )> {
271 static constexpr bool is_null =
false;
272 using key =
typename AssociativeContainer::key_type;
273 using value =
typename AssociativeContainer::mapped_type;
274 static constexpr auto parse_type = JsonParseTypes::KeyValue;
276 static constexpr bool type_map_found =
true;
280 DAW_CPP20_CONCEPT is_deduced_array_v =
281 not has_json_data_contract_trait_v<T> and
282 not is_associative_container_v<T> and concepts::is_container_v<T> and
285 template<
typename Container,
typename AllowRawString>
287 struct json_deduced_type_map<
289 AllowRawString DAW_ENABLEIF_S( is_deduced_array_v<Container> )> {
290 static constexpr bool is_null =
false;
291 using value =
typename Container::value_type;
292 static constexpr auto parse_type = JsonParseTypes::Array;
294 static constexpr bool type_map_found =
true;
297#if defined( DAW_JSON_USE_CONCEPTS )
298 template<
typename T,
typename AllowRawString>
299 inline constexpr bool detected_deduced_type_map_v =
requires {
300 requires json_deduced_type_map<T, AllowRawString>::type_map_found;
303 template<
typename,
typename,
typename =
void>
304 inline constexpr bool detected_deduced_type_map_v =
false;
306 template<
typename T,
typename AllowRawString>
307 inline constexpr bool detected_deduced_type_map_v<
309 std::void_t<
decltype( json_deduced_type_map<
310 T, AllowRawString>::type_map_found )>> =
311 json_deduced_type_map<T, AllowRawString>::type_map_found;
313 template<
typename T,
typename AllowRawString>
314 DAW_CPP20_CONCEPT has_nullable_type_map_v =
315 concepts::is_nullable_value_v<T> and
316 not has_json_data_contract_trait_v<T> and
317 detected_deduced_type_map_v<concepts::nullable_value_type_t<T>,
320 template<
typename T,
typename AllowRawString>
321 DAW_REQUIRES( has_nullable_type_map_v<T, AllowRawString> )
322 struct json_deduced_type_map<
323 T, AllowRawString DAW_ENABLEIF_S(
324 has_nullable_type_map_v<T, AllowRawString> )> {
325 static constexpr bool is_null =
true;
326 using sub_type = concepts::nullable_value_type_t<T>;
327 using type = json_deduced_type_map<sub_type, AllowRawString>;
328 static constexpr auto parse_type = type::parse_type;
329 static constexpr bool type_map_found =
true;
332 template<
typename T,
typename AllowRawString = std::true_type>
333 DAW_CPP20_CONCEPT has_deduced_type_mapping_v =
334 json_deduced_type_map<T, AllowRawString>::type_map_found;
336 template<
typename... Ts>
337 DAW_CPP20_CONCEPT are_deduced_type_mapped_v =
338 ( has_deduced_type_mapping_v<Ts> and ... );
340 template<
typename Mapped,
bool Found = true>
341 struct json_link_quick_map_type {
342 static constexpr bool value = Found;
343 using mapped_type = Mapped;
346 template<JsonParseTypes Value>
347 DAW_CPP20_CONCEPT is_arithmetic_parse_type_v =
348 daw::traits::equal_to_any_of_v<Value, JsonParseTypes::Signed,
349 JsonParseTypes::Unsigned,
350 JsonParseTypes::Real>;
352 template<
typename T,
typename AllowRawString = std::true_type>
353 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( )
noexcept;
355 template<
typename T,
typename AllowRawString>
356 struct deduced_element {
358 typename decltype( json_deduced_type_impl<T,
359 AllowRawString>( ) )::type;
366 template<
typename T,
typename AllowRawString>
367 using deduced_element_t =
368 typename daw::conditional_t<AllowRawString::value,
369 daw::traits::identity<T>,
370 deduced_element<T, AllowRawString>>::type;
372 template<
typename Tuple,
typename AllowRawString,
373 typename = std::make_index_sequence<std::tuple_size_v<Tuple>>>
374 struct deduced_tuple_types;
376 template<
typename Tuple,
typename AllowRawString, std::size_t... Is>
377 struct deduced_tuple_types<Tuple, AllowRawString,
378 std::index_sequence<Is...>> {
379 using type = std::tuple<deduced_element_t<
380 daw::remove_cvref_t<std::tuple_element_t<Is, Tuple>>,
386 template<
typename Tuple,
typename AllowRawString>
387 using deduced_tuple_types_t =
typename daw::conditional_t<
388 AllowRawString::value, daw::traits::identity<use_default>,
389 deduced_tuple_types<Tuple, AllowRawString>>::type;
391 template<
typename T,
typename AllowRawString = std::true_type>
392 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_link_quick_map( )
noexcept {
393 if constexpr( is_a_json_type_v<T> ) {
394 return json_link_quick_map_type<T>{ };
395 }
else if constexpr( has_deduced_type_mapping_v<T, AllowRawString> ) {
396 using mapped_type_t = json_deduced_type_map<T, AllowRawString>;
397 using parse_type = daw::constant<mapped_type_t::parse_type>;
398 using is_null = daw::constant<mapped_type_t::is_null>;
399 if constexpr( parse_type::value == JsonParseTypes::Unknown ) {
400 if constexpr( is_null::value ) {
401 if constexpr( has_json_data_contract_trait_v<
402 typename mapped_type_t::sub_type> ) {
403 return json_link_quick_map_type<
404 json_base::json_class_null<T>>{ };
406 return json_link_quick_map_type<json_base::json_raw_null<T>>{ };
409 return json_link_quick_map_type<json_base::json_raw<T>>{ };
411 }
else if constexpr( parse_type::value ==
412 JsonParseTypes::StringRaw ) {
413 if constexpr( is_null::value ) {
414 return json_link_quick_map_type<
415 json_base::json_string_raw_null<T>>{ };
417 return json_link_quick_map_type<json_base::json_string_raw<T>>{ };
419 }
else if constexpr( parse_type::value ==
420 JsonParseTypes::StringEscaped ) {
421 if constexpr( is_null::value ) {
422 return json_link_quick_map_type<
423 json_base::json_string_null<T>>{ };
425 return json_link_quick_map_type<json_base::json_string<T>>{ };
427 }
else if constexpr( parse_type::value ==
428 JsonParseTypes::StringInsitu ) {
429 if constexpr( is_null::value ) {
430 return json_link_quick_map_type<
431 json_base::json_string_insitu_null<T>>{ };
433 return json_link_quick_map_type<
434 json_base::json_string_insitu<T>>{ };
436 }
else if constexpr( parse_type::value == JsonParseTypes::Bool ) {
437 if constexpr( is_null::value ) {
438 return json_link_quick_map_type<json_base::json_bool_null<T>>{ };
440 return json_link_quick_map_type<json_base::json_bool<T>>{ };
442 }
else if constexpr( is_arithmetic_parse_type_v<parse_type::value> ) {
443 if constexpr( is_null::value ) {
444 return json_link_quick_map_type<
445 json_base::json_number_null<T>>{ };
447 return json_link_quick_map_type<json_base::json_number<T>>{ };
449 }
else if constexpr( parse_type::value == JsonParseTypes::Tuple ) {
450 if constexpr( is_null::value ) {
451 using tp_t = json_details::unwrapped_t<T>;
452 return json_link_quick_map_type<json_base::json_tuple_null<
454 deduced_tuple_types_t<tp_t, AllowRawString>>>{ };
456 return json_link_quick_map_type<json_base::json_tuple<
458 deduced_tuple_types_t<T, AllowRawString>>>{ };
460 }
else if constexpr( parse_type::value == JsonParseTypes::KeyValue ) {
461 if constexpr( is_null::value ) {
462 using b_t =
typename mapped_type_t::type;
463 using k_t = deduced_element_t<typename b_t::key, AllowRawString>;
465 deduced_element_t<typename b_t::value, AllowRawString>;
466 return json_link_quick_map_type<
467 json_base::json_key_value_null<T, v_t, k_t>>{ };
470 deduced_element_t<typename mapped_type_t::key, AllowRawString>;
471 using v_t = deduced_element_t<
typename mapped_type_t::value,
473 return json_link_quick_map_type<
474 json_base::json_key_value<T, v_t, k_t>>{ };
476 }
else if constexpr( parse_type::value == JsonParseTypes::Array ) {
477 if constexpr( is_null::value ) {
478 using b_t =
typename mapped_type_t::type;
480 deduced_element_t<typename b_t::value, AllowRawString>;
481 return json_link_quick_map_type<json_base::json_nullable<
483 json_base::json_array<v_t, json_details::unwrapped_t<T>>>>{ };
485 using v_t = deduced_element_t<
typename mapped_type_t::value,
487 return json_link_quick_map_type<json_base::json_array<v_t, T>>{ };
489#if defined( DAW_JSON_HAS_REFLECTION )
490 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
491 return json_link_quick_map_type<
492 json_base::json_reflected_class<T>>{ };
495 return json_link_quick_map_type<void, false>{ };
497#if defined( DAW_JSON_HAS_REFLECTION )
498 }
else if constexpr( refl_details::PotentiallyReflectable<T> ) {
499 return json_link_quick_map_type<
500 json_base::json_reflected_class<T>>{ };
503 return json_link_quick_map_type<void, false>{ };
508 template<
typename T,
typename AllowRawString = std::true_type>
509 DAW_CPP20_CONCEPT has_json_link_quick_map_v =
510 decltype( json_link_quick_map<T, AllowRawString>( ) )::value;
513 template<
typename T,
typename AllowRawString = std::true_type>
514 using json_link_quick_map_t =
515 typename decltype( json_link_quick_map<
516 T, AllowRawString>( ) )::mapped_type;
518 template<
typename JsonType>
519 struct json_class_map_type {
524 struct is_json_class_map : std::false_type {};
528 inline constexpr bool is_json_class_map_v =
529 has_json_data_contract_trait_v<T> and
530 is_json_class_map_v<json_data_contract_trait_t<T>>;
534 inline constexpr bool is_char_pointer_v =
535 std::is_pointer_v<T> and
536 std::is_same_v<std::remove_cv_t<std::remove_pointer_t<T>>,
char>;
540 inline constexpr bool is_char_array_v =
541 std::rank_v<T> == 1 and
542 std::is_same_v<std::remove_cv_t<std::remove_extent_t<T>>,
char>;
544 template<
typename T,
typename AllowRawString>
545 DAW_ATTRIB_INLINE DAW_CONSTEVAL
auto json_deduced_type_impl( )
noexcept {
546 if constexpr( is_char_array_v<T> and not AllowRawString::value ) {
547 return daw::traits::identity<
548 json_base::json_string_insitu<daw::string_view>>{ };
549 }
else if constexpr( is_a_basic_json_value<T> ) {
550 return daw::traits::identity<json_base::json_raw<T>>{ };
551#if defined( DAW_JSON_HAS_REFLECTION )
552 }
else if constexpr( refl_details::HasTypeLevelAnnotation<T> ) {
553 return daw::traits::identity<
554 refl_details::type_annotation_mapping_t<T>>{ };
556 }
else if constexpr( is_an_ordered_member_v<T> ) {
558 return daw::traits::identity<type>{ };
559 }
else if constexpr( has_json_data_contract_trait_v<T> ) {
560 static_assert( not std::is_same_v<T, void> );
562 using type = json_base::json_class<T>;
564 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
565 "Detection failure" );
566 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
567 "Detection failure" );
568 return daw::traits::identity<type>{ };
569 }
else if constexpr( has_json_link_quick_map_v<T, AllowRawString> ) {
570 static_assert( not std::is_same_v<T, void> );
571 using type = json_link_quick_map_t<T, AllowRawString>;
572 using rcvref_type = remove_cvref_t<type>;
573 static_assert( not std::is_same_v<rcvref_type, void>,
574 "Detection failure" );
575 static_assert( not is_nonesuch_v<rcvref_type>,
"Detection failure" );
576 return daw::traits::identity<type>{ };
577 }
else if constexpr( is_a_json_type_v<T> ) {
578 static_assert( not std::is_same_v<T, void> );
580 typename daw::conditional_t<is_json_class_map_v<T>,
581 json_class_map_type<T>,
582 daw::traits::identity<T>>::type;
583 static_assert( not std::is_same_v<daw::remove_cvref_t<type>,
void>,
584 "Detection failure" );
585 static_assert( not is_nonesuch_v<remove_cvref_t<type>>,
586 "Detection failure" );
587 return daw::traits::identity<type>{ };
588 }
else if constexpr( concepts::is_nullable_value_v<T> ) {
589 using value_type = concepts::nullable_value_type_t<T>;
590 using sub_type =
typename decltype( json_deduced_type_impl<
592 AllowRawString>( ) )::type;
593 using type = json_base::json_nullable<T, sub_type>;
594 return daw::traits::identity<type>{ };
595 }
else if constexpr( concepts::is_container_v<T> ) {
596 using type = json_base::json_array<
597 deduced_element_t<typename T::value_type, AllowRawString>,
599 return daw::traits::identity<type>{ };
600 }
else if constexpr( std::is_empty_v<T> and
601 std::is_default_constructible_v<T> ) {
603 using type = json_details::json_empty_class<T>;
604 return daw::traits::identity<type>{ };
605#if not defined( DAW_JSON_HAS_REFLECTION )
606 }
else if constexpr( can_convert_to_tuple_v<T> ) {
607 using type = json_base::json_tuple<T>;
608 return daw::traits::identity<type>{ };
611 static_assert( daw::deduced_false_v<T>,
612 "Could not deduced data contract type and there is no "
613 "json_data_contract_specialization" );
617 template<
typename T,
typename AllowRawString = std::true_type>
618 using json_deduced_type =
typename DAW_TYPEOF(
619 json_deduced_type_impl<T, AllowRawString>( ) )::type;
625 template<
typename JsonClass,
typename Value>
626 using json_serialize_deduced_type =
typename daw::conditional_t<
627 std::is_same_v<use_default, JsonClass>,
628 ident_trait<json_deduced_type, Value, std::false_type>,
630 is_a_json_type_v<JsonClass>,
631 ident_trait<json_deduced_type, JsonClass>,
632 ident_trait<json_deduced_type, JsonClass, std::false_type>>>::type;
634 template<
typename T,
typename AllowRawString = std::true_type>
635 DAW_CPP20_CONCEPT has_json_deduced_type_v =
636 not std::is_same_v<json_deduced_type<T, AllowRawString>,
639 template<
typename... Ts>
640 DAW_CPP20_CONCEPT all_have_deduced_type_v =
641 ( has_json_deduced_type_v<Ts> and ... );
643 template<
typename JsonElement,
typename Container,
typename Constructor>
644 struct json_constructor<
645 json_base::
json_array<JsonElement, Container, Constructor>> {
646 using json_element_t = json_deduced_type<JsonElement>;
647 using json_element_parse_to_t = json_result_t<json_element_t>;
650 daw::conditional_t<std::is_same_v<Container, use_default>,
651 std::vector<json_element_parse_to_t>, Container>;
654 daw::conditional_t<std::is_same_v<use_default, Constructor>,
658 daw::is_callable_v<type, json_element_parse_to_t
const *,
659 json_element_parse_to_t
const *>,
660 "Constructor must support copy and/or move construction" );
663 template<
typename JsonElement,
typename Container,
typename Constructor>
665 json_base::
json_array<JsonElement, Container, Constructor>> {
666 using constructor_t =
typename json_constructor<
667 json_base::json_array<JsonElement, Container, Constructor>>::type;
668 using json_element_t = json_deduced_type<JsonElement>;
669 using json_element_parse_to_t =
670 typename json_result<json_element_t>::type;
672 std::invoke_result_t<constructor_t, json_element_parse_to_t
const *,
673 json_element_parse_to_t
const *>;
677 DAW_CPP20_CONCEPT has_unnamed_default_type_mapping_v =
678 has_json_deduced_type_v<T>;
680 template<
typename JsonMember>
681 using from_json_result_t = json_result_t<json_deduced_type<JsonMember>>;
683 template<
typename Constructor,
typename... Members>
684 using json_class_parse_result_impl2 =
685 std::invoke_result_t<Constructor, json_result_t<Members>...>;
687 template<
typename Constructor,
typename... Members>
688 using json_class_parse_result_impl =
689 daw::detected_t<json_class_parse_result_impl2, Constructor, Members...>;
691 template<
typename Constructor,
typename... Members>
692 struct could_not_construct_from_members_error;
694 template<
typename Constructor,
typename... Members>
695 using json_class_parse_result_t =
typename daw::conditional_t<
696 daw::is_callable_v<Constructor, json_result_t<Members>...>,
697 std::invoke_result<Constructor, json_result_t<Members>...>,
698 daw::traits::identity<could_not_construct_from_members_error<
699 Constructor, Members...>>>::type;
701 template<
typename JsonMember>
702 using dependent_member_t =
typename JsonMember::dependent_member;
704 template<
typename JsonMember,
typename =
void>
705 inline constexpr bool has_dependent_member_v =
false;
707 template<
typename JsonMember>
708 inline constexpr bool has_dependent_member_v<
709 JsonMember, std::void_t<dependent_member_t<JsonMember>>> =
true;
712 T::member_type::dependent_member );
714 template<
typename JsonMember>
716 inline constexpr bool has_dependent_member_v<
717 JsonMember DAW_ENABLEIF_S( is_json_nullable_v<JsonMember> )> =
718 has_nullable_dependent_member_v<JsonMember>;
720 template<
typename Constructor>
721 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr auto
722 construct_nullable_empty( ) {
723 if constexpr( daw::is_callable_v<
725 concepts::construct_nullable_with_empty_t> ) {
726 return Constructor{ }( concepts::construct_nullable_with_empty );
728 return Constructor{ }( );