diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index c509945d..30f13489 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -498,6 +498,29 @@ namespace chaiscript { func); } + namespace detail { + template + struct is_std_vector : std::false_type {}; + + template + struct is_std_vector> : std::true_type {}; + + template + T convert_vector_element(const Boxed_Value &bv) { + if constexpr (is_std_vector::value) { + const auto &inner = Cast_Helper &>::cast(bv, nullptr); + T result; + result.reserve(inner.size()); + for (const Boxed_Value &elem : inner) { + result.push_back(convert_vector_element(elem)); + } + return result; + } else { + return Cast_Helper::cast(bv, nullptr); + } + } + } // namespace detail + template Type_Conversion vector_conversion() { auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { @@ -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::cast(bv, nullptr)); + vec.push_back(detail::convert_vector_element(bv)); } return Boxed_Value(std::move(vec)); diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 4e0080de..b8ffe144 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1806,6 +1806,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::bootstrap::standard_library::vector_type>("VectorDouble", *m); + chaiscript::bootstrap::standard_library::vector_type>>("VectorVectorDouble", *m); + m->add(chaiscript::vector_conversion>()); + m->add(chaiscript::vector_conversion>>()); + chai.add(m); + + chai.add(chaiscript::fun([](const std::vector> &v) -> double { + double sum = 0; + for (const auto &inner : v) { + for (const auto d : inner) { + sum += d; + } + } + return sum; + }), "sum_nested"); + + CHECK(chai.eval("sum_nested([[1.0, 2.0], [3.0, 4.0]])") == Approx(10.0)); + + CHECK(chai.eval( + "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 call_stack member. // This failed to compile with C++20 on clang/libc++ when AST_Node_Trace