DAW JSON Link
Loading...
Searching...
No Matches
daw_json_construct_value.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
12
13#include "daw/daw_allocator_construct.h"
15
16#include <daw/daw_attributes.h>
17#include <daw/daw_fwd_pack_apply.h>
18
19#include <cstddef>
20#include <utility>
21
22namespace daw::json {
23 inline namespace DAW_JSON_VER {
24 namespace json_details {
25 template<typename Value, typename Constructor, typename ParseState,
26 typename... Args>
27 DAW_ATTRIB_INLINE static constexpr auto
28 construct_value( ParseState &parse_state, Args &&...args ) {
29 // Silence MSVC warning, used in other if constexpr case
30 (void)parse_state;
31 if constexpr( ParseState::has_allocator ) {
32 auto alloc = parse_state.template get_allocator_for<Value>( );
33 return daw::try_alloc_construct<Value, Constructor>(
34 std::move( alloc ), DAW_FWD( args )... );
35 } else {
36 static_assert(
37 daw::is_callable_v<Constructor, Args...>,
38 "Unable to construct value with the supplied arguments" );
39 return Constructor{ }( DAW_FWD( args )... );
40 }
41 }
42
43#if not defined( DAW_JSON_USE_GENERIC_LAMBDAS )
44 template<typename Constructor>
45 struct construct_value_tp_invoke_t {
46 template<typename... TArgs, std::size_t... Is>
47 DAW_ATTRIB_INLINE constexpr auto
48 operator( )( fwd_pack<TArgs...> &&tp,
49 std::index_sequence<Is...> ) const {
50 return Constructor{ }( get<Is>( std::move( tp ) )... );
51 }
52
53 template<typename... TArgs, typename Allocator, std::size_t... Is>
54 DAW_ATTRIB_INLINE constexpr auto
55 operator( )( fwd_pack<TArgs...> &&tp, Allocator &alloc,
56 std::index_sequence<Is...> ) const {
57 return Constructor{ }( get<Is>( std::move( tp ) )...,
58 DAW_FWD( alloc ) );
59 }
60
61 template<typename Alloc, typename... TArgs, std::size_t... Is>
62 DAW_ATTRIB_INLINE constexpr auto
63 operator( )( std::allocator_arg_t, Alloc &&alloc,
64 fwd_pack<TArgs...> &&tp,
65 std::index_sequence<Is...> ) const {
66
67 return Constructor{ }( std::allocator_arg,
68 DAW_FWD( alloc ),
69 get<Is>( std::move( tp ) )... );
70 }
71 };
72 template<typename Constructor>
73 inline constexpr auto construct_value_tp_invoke =
74 construct_value_tp_invoke_t<Constructor>{ };
75#endif
76
77 template<typename Value, typename Constructor, typename ParseState,
78 typename... Args>
79 DAW_ATTRIB_FLATINLINE static constexpr auto
80 construct_value_tp( ParseState &parse_state,
81 fwd_pack<Args...> &&tp_args ) {
82
83#if defined( DAW_JSON_USE_GENERIC_LAMBDAS )
84 if constexpr( ParseState::has_allocator ) {
85 // ParseState has a user allocator, pass that if we can to the
86 // constructed value
87 using alloc_t =
88 typename ParseState::template allocator_type_as<Value>;
89 auto alloc = parse_state.template get_allocator_for<Value>( );
90 // There are several ways that the allocator is passed on
91 if constexpr( daw::is_callable_v<Constructor, Args..., alloc_t> ) {
92 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
93 // Type( args..., alloc )
94 return Constructor{ }( get<Is>( std::move( tp_args ) )...,
95 std::move( alloc ) );
96 }( std::make_index_sequence<sizeof...( Args )>{ } );
97 } else if constexpr( daw::is_callable_v<Constructor,
98 std::allocator_arg_t,
99 alloc_t,
100 Args...> ) {
101 // Type( std::allocator_arg, alloc, args... )
102 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
103 return Constructor{ }( std::allocator_arg,
104 std::move( alloc ),
105 get<Is>( std::move( tp_args ) )... );
106 }( std::make_index_sequence<sizeof...( Args )>{ } );
107 } else {
108 // This type does not take a known allocator in the constructor,
109 // fallback to normal construction
110 // Type( args... )
111 static_assert(
112 daw::is_callable_v<Constructor, Args...>,
113 "Unable to construct value with the supplied arguments" );
114 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
115 return Constructor{ }( get<Is>( std::move( tp_args ) )... );
116 }( std::make_index_sequence<sizeof...( Args )>{ } );
117 }
118 } else {
119 // Type( args... )
120 // No ParseState user allocator
121 // Silence MSVC warning, used in other if constexpr case
122 (void)parse_state;
123 static_assert(
124 daw::is_callable_v<Constructor, Args...>,
125 "Unable to construct value with the supplied arguments" );
126 return [&]<std::size_t... Is>( std::index_sequence<Is...> ) {
127 return Constructor{ }( get<Is>( std::move( tp_args ) )... );
128 }( std::make_index_sequence<sizeof...( Args )>{ } );
129 }
130#else
131 if constexpr( ParseState::has_allocator ) {
132 // ParseState has a user allocator, pass that if we can to the
133 // constructed value
134 using alloc_t =
135 typename ParseState::template allocator_type_as<Value>;
136 auto alloc = parse_state.template get_allocator_for<Value>( );
137 if constexpr( daw::is_callable_v<Constructor, Args..., alloc_t> ) {
138 // Type( args..., alloc )
139 return construct_value_tp_invoke<Constructor>(
140 std::move( tp_args ),
141 std::move( alloc ),
142 std::index_sequence_for<Args...>{ } );
143 } else if constexpr( daw::is_callable_v<Constructor,
144 std::allocator_arg_t,
145 alloc_t,
146 Args...> ) {
147 // Type( std::allocator_arg, alloc, args... )
148 return construct_value_tp_invoke<Constructor>(
149 std::allocator_arg,
150 std::move( alloc ),
151 std::move( tp_args ),
152 std::index_sequence_for<Args...>{ } );
153 } else {
154 // This type does not take a known allocator in the constructor,
155 // fallback to normal construction
156 // Type( args... )
157 static_assert(
158 daw::is_callable_v<Constructor, Args...>,
159 "Unable to construct value with the supplied arguments" );
160 return construct_value_tp_invoke<Constructor>(
161 std::move( tp_args ), std::index_sequence_for<Args...>{ } );
162 }
163 } else {
164 // No ParseState user allocator
165 // Silence MSVC warning, used in other if constexpr case
166 // Type( args... )
167 (void)parse_state;
168 static_assert(
169 daw::is_callable_v<Constructor, Args...>,
170 "Unable to construct value with the supplied arguments" );
171 return construct_value_tp_invoke<Constructor>(
172 std::move( tp_args ), std::index_sequence_for<Args...>{ } );
173 }
174#endif
175 }
176 } // namespace json_details
177 } // namespace DAW_JSON_VER
178} // namespace daw::json
Customization point traits.
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition version.h:20