Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion include/chaiscript/dispatchkit/type_conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,29 @@ namespace chaiscript {
func);
}

namespace detail {
template<typename T>
struct is_std_vector : std::false_type {};

template<typename T, typename A>
struct is_std_vector<std::vector<T, A>> : std::true_type {};

template<typename T>
T convert_vector_element(const Boxed_Value &bv) {
if constexpr (is_std_vector<T>::value) {
const auto &inner = Cast_Helper<const std::vector<Boxed_Value> &>::cast(bv, nullptr);
T result;
result.reserve(inner.size());
for (const Boxed_Value &elem : inner) {
result.push_back(convert_vector_element<typename T::value_type>(elem));
}
return result;
} else {
return Cast_Helper<T>::cast(bv, nullptr);
}
}
} // namespace detail

template<typename To>
Type_Conversion vector_conversion() {
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
Expand All @@ -506,7 +529,7 @@ namespace chaiscript {
To vec;
vec.reserve(from_vec.size());
for (const Boxed_Value &bv : from_vec) {
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
vec.push_back(detail::convert_vector_element<typename To::value_type>(bv));
}

return Boxed_Value(std::move(vec));
Expand Down
29 changes: 29 additions & 0 deletions unittests/compiled_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1802,6 +1802,35 @@ TEST_CASE("push_back on script vector with vector_conversion") {
) == "hello,world");
}

TEST_CASE("vector of vectors conversion (issue #374)") {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());

auto m = std::make_shared<chaiscript::Module>();
chaiscript::bootstrap::standard_library::vector_type<std::vector<double>>("VectorDouble", *m);
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::vector<double>>>("VectorVectorDouble", *m);
m->add(chaiscript::vector_conversion<std::vector<double>>());
m->add(chaiscript::vector_conversion<std::vector<std::vector<double>>>());
chai.add(m);

chai.add(chaiscript::fun([](const std::vector<std::vector<double>> &v) -> double {
double sum = 0;
for (const auto &inner : v) {
for (const auto d : inner) {
sum += d;
}
}
return sum;
}), "sum_nested");

CHECK(chai.eval<double>("sum_nested([[1.0, 2.0], [3.0, 4.0]])") == Approx(10.0));

CHECK(chai.eval<bool>(
"auto v = VectorVectorDouble();"
"v = [[1.0, 2.0], [3.0, 4.0]];"
"v.size() == 2"
));
}

// Regression test for issue #607: AST_Node_Trace must be a complete type
// when used in eval_error's std::vector<AST_Node_Trace> call_stack member.
// This failed to compile with C++20 on clang/libc++ when AST_Node_Trace
Expand Down
Loading