|
30 | 30 |
|
31 | 31 | namespace BT
|
32 | 32 | {
|
| 33 | +// Helper trait to check if a type is a std::vector |
| 34 | +template <typename T> |
| 35 | +struct is_vector : std::false_type {}; |
| 36 | + |
| 37 | +template <typename T, typename A> |
| 38 | +struct is_vector<std::vector<T, A>> : std::true_type {}; |
33 | 39 |
|
34 | 40 | /// This information is used mostly by the XMLParser.
|
35 | 41 | struct TreeNodeManifest
|
@@ -521,6 +527,26 @@ inline Expected<Timestamp> TreeNode::getInputStamped(const std::string& key,
|
521 | 527 |
|
522 | 528 | if(!entry->value.empty())
|
523 | 529 | {
|
| 530 | + // Support vector<Any> -> vector<typename T::value_type> conversion. |
| 531 | + // Only want to compile this path when T is a vector type. |
| 532 | + if constexpr (is_vector<T>::value) |
| 533 | + { |
| 534 | + if (!std::is_same_v<T, std::vector<Any>> && any_value.type() == typeid(std::vector<Any>)) |
| 535 | + { |
| 536 | + // If the object was originally placed on the blackboard as a vector<Any>, attempt to unwrap the vector |
| 537 | + // elements according to the templated type. |
| 538 | + auto any_vec = any_value.cast<std::vector<Any>>(); |
| 539 | + if (!any_vec.empty() && any_vec.front().type() != typeid(typename T::value_type)) |
| 540 | + { |
| 541 | + return nonstd::make_unexpected("Invalid cast requested from vector<Any> to vector<typename T::value_type>." |
| 542 | + " Element type does not align."); |
| 543 | + } |
| 544 | + destination = T(); |
| 545 | + std::transform(any_vec.begin(), any_vec.end(), std::back_inserter(destination), |
| 546 | + [](Any &element) { return element.cast<typename T::value_type>(); }); |
| 547 | + return Timestamp{ entry->sequence_id, entry->stamp }; |
| 548 | + } |
| 549 | + } |
524 | 550 | if(!std::is_same_v<T, std::string> && any_value.isString())
|
525 | 551 | {
|
526 | 552 | destination = parseString<T>(any_value.cast<std::string>());
|
|
0 commit comments