@@ -106,60 +106,121 @@ class Attribute : public auxiliary::Variant<Datatype, attribute_types>
106106namespace detail
107107{
108108 template <typename T, typename U>
109- auto doConvert (T *pv) -> std::variant<U, std::runtime_error>
109+ auto doConvert (T const *pv) -> std::variant<U, std::runtime_error>
110110 {
111111 (void )pv;
112112 if constexpr (std::is_convertible_v<T, U>)
113113 {
114114 return {static_cast <U>(*pv)};
115115 }
116+ else if constexpr (
117+ std::is_same_v<T, std::string> && auxiliary::IsChar_v<U>)
118+ {
119+ if (pv->size () == 1 )
120+ {
121+ return static_cast <U>(pv->at (0 ));
122+ }
123+ else
124+ {
125+ return {
126+ std::runtime_error (" getCast: cast from string to char only "
127+ " possible if string has length 1." )};
128+ }
129+ }
130+ else if constexpr (
131+ auxiliary::IsChar_v<T> && std::is_same_v<U, std::string>)
132+ {
133+ return std::string (1 , *pv);
134+ }
116135 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsVector_v<U>)
117136 {
137+ U res{};
138+ res.reserve (pv->size ());
118139 if constexpr (std::is_convertible_v<
119140 typename T::value_type,
120141 typename U::value_type>)
121142 {
122- U res{};
123- res.reserve (pv->size ());
124143 std::copy (pv->begin (), pv->end (), std::back_inserter (res));
125144 return {res};
126145 }
127146 else
128147 {
129- return {
130- std::runtime_error (" getCast: no vector cast possible." )};
148+ // try a dynamic conversion recursively
149+ for (auto const &val : *pv)
150+ {
151+ auto conv = doConvert<
152+ typename T::value_type,
153+ typename U::value_type>(&val);
154+ if (auto conv_val =
155+ std::get_if<typename U::value_type>(&conv);
156+ conv_val)
157+ {
158+ res.push_back (std::move (*conv_val));
159+ }
160+ else
161+ {
162+ auto exception = std::get<std::runtime_error>(conv);
163+ return {std::runtime_error (
164+ std::string (
165+ " getCast: no vector cast possible, recursive "
166+ " error: " ) +
167+ exception.what ())};
168+ }
169+ }
170+ return {res};
131171 }
132172 }
133173 // conversion cast: array to vector
134174 // if a backend reports a std::array<> for something where
135175 // the frontend expects a vector
136176 else if constexpr (auxiliary::IsArray_v<T> && auxiliary::IsVector_v<U>)
137177 {
178+ U res{};
179+ res.reserve (pv->size ());
138180 if constexpr (std::is_convertible_v<
139181 typename T::value_type,
140182 typename U::value_type>)
141183 {
142- U res{};
143- res.reserve (pv->size ());
144184 std::copy (pv->begin (), pv->end (), std::back_inserter (res));
145185 return {res};
146186 }
147187 else
148188 {
149- return {std::runtime_error (
150- " getCast: no array to vector conversion possible." )};
189+ // try a dynamic conversion recursively
190+ for (auto const &val : *pv)
191+ {
192+ auto conv = doConvert<
193+ typename T::value_type,
194+ typename U::value_type>(&val);
195+ if (auto conv_val =
196+ std::get_if<typename U::value_type>(&conv);
197+ conv_val)
198+ {
199+ res.push_back (std::move (*conv_val));
200+ }
201+ else
202+ {
203+ auto exception = std::get<std::runtime_error>(conv);
204+ return {std::runtime_error (
205+ std::string (
206+ " getCast: no array to vector conversion "
207+ " possible, recursive error: " ) +
208+ exception.what ())};
209+ }
210+ }
211+ return {res};
151212 }
152213 }
153214 // conversion cast: vector to array
154215 // if a backend reports a std::vector<> for something where
155216 // the frontend expects an array
156217 else if constexpr (auxiliary::IsVector_v<T> && auxiliary::IsArray_v<U>)
157218 {
219+ U res{};
158220 if constexpr (std::is_convertible_v<
159221 typename T::value_type,
160222 typename U::value_type>)
161223 {
162- U res{};
163224 if (res.size () != pv->size ())
164225 {
165226 return std::runtime_error (
@@ -175,24 +236,60 @@ namespace detail
175236 }
176237 else
177238 {
178- return {std::runtime_error (
179- " getCast: no vector to array conversion possible." )};
239+ // try a dynamic conversion recursively
240+ for (size_t i = 0 ; i <= res.size (); ++i)
241+ {
242+ auto const &val = (*pv)[i];
243+ auto conv = doConvert<
244+ typename T::value_type,
245+ typename U::value_type>(&val);
246+ if (auto conv_val =
247+ std::get_if<typename U::value_type>(&conv);
248+ conv_val)
249+ {
250+ res[i] = std::move (*conv_val);
251+ }
252+ else
253+ {
254+ auto exception = std::get<std::runtime_error>(conv);
255+ return {std::runtime_error (
256+ std::string (
257+ " getCast: no vector to array conversion "
258+ " possible, recursive error: " ) +
259+ exception.what ())};
260+ }
261+ }
262+ return {res};
180263 }
181264 }
182265 // conversion cast: turn a single value into a 1-element vector
183266 else if constexpr (auxiliary::IsVector_v<U>)
184267 {
268+ U res{};
269+ res.reserve (1 );
185270 if constexpr (std::is_convertible_v<T, typename U::value_type>)
186271 {
187- U res{};
188- res.reserve (1 );
189272 res.push_back (static_cast <typename U::value_type>(*pv));
190273 return {res};
191274 }
192275 else
193276 {
194- return {std::runtime_error (
195- " getCast: no scalar to vector conversion possible." )};
277+ // try a dynamic conversion recursively
278+ auto conv = doConvert<T, typename U::value_type>(pv);
279+ if (auto conv_val = std::get_if<typename U::value_type>(&conv);
280+ conv_val)
281+ {
282+ res.push_back (std::move (*conv_val));
283+ return {res};
284+ }
285+ else
286+ {
287+ auto exception = std::get<std::runtime_error>(conv);
288+ return {std::runtime_error (
289+ std::string (" getCast: no scalar to vector conversion "
290+ " possible, recursive error: " ) +
291+ exception.what ())};
292+ }
196293 }
197294 }
198295 else
0 commit comments