diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index f56304d7..5bbc17e0 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -170,18 +171,22 @@ namespace chaiscript::bootstrap::standard_library { /// http://www.sgi.com/tech/stl/Assignable.html template void assignable_type(const std::string &type, Module &m) { - copy_constructor(type, m); - operators::assign(m); + if constexpr (std::is_copy_constructible_v) { + copy_constructor(type, m); + operators::assign(m); + } } /// Add container resize concept to the given ContainerType /// http://www.cplusplus.com/reference/stl/ template void resizable_type(const std::string & /*type*/, Module &m) { - m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type &val) { - return a->resize(n, val); - }), - "resize"); + if constexpr (std::is_copy_constructible_v) { + m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type &val) { + return a->resize(n, val); + }), + "resize"); + } m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); }), "resize"); } @@ -213,13 +218,15 @@ namespace chaiscript::bootstrap::standard_library { /// http://www.sgi.com/tech/stl/Sequence.html template void sequence_type(const std::string & /*type*/, Module &m) { - m.add(fun(&detail::insert_at), []() -> std::string { - if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { - return "insert_ref_at"; - } else { - return "insert_at"; - } - }()); + if constexpr (std::is_copy_constructible_v) { + m.add(fun(&detail::insert_at), []() -> std::string { + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + return "insert_ref_at"; + } else { + return "insert_at"; + } + }()); + } m.add(fun(&detail::erase_at), "erase_at"); } @@ -245,27 +252,29 @@ namespace chaiscript::bootstrap::standard_library { }), "back"); - using push_back = void (ContainerType::*)(const typename ContainerType::value_type &); - m.add(fun(static_cast(&ContainerType::push_back)), [&]() -> std::string { - if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { - m.eval("# Pushes the second value onto the container while making a clone of the value\n" - "def push_back(" - + type - + " container, x)\n" - "{ \n" - " if (x.is_var_return_value()) {\n" - " x.reset_var_return_value() \n" - " container.push_back_ref(x) \n" - " } else { \n" - " container.push_back_ref(clone(x)); \n" - " }\n" - "} \n"); + if constexpr (std::is_copy_constructible_v) { + using push_back = void (ContainerType::*)(const typename ContainerType::value_type &); + m.add(fun(static_cast(&ContainerType::push_back)), [&]() -> std::string { + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + m.eval("# Pushes the second value onto the container while making a clone of the value\n" + "def push_back(" + + type + + " container, x)\n" + "{ \n" + " if (x.is_var_return_value()) {\n" + " x.reset_var_return_value() \n" + " container.push_back_ref(x) \n" + " } else { \n" + " container.push_back_ref(clone(x)); \n" + " }\n" + "} \n"); - return "push_back_ref"; - } else { - return "push_back"; - } - }()); + return "push_back_ref"; + } else { + return "push_back"; + } + }()); + } m.add(fun(&ContainerType::pop_back), "pop_back"); } @@ -295,25 +304,27 @@ namespace chaiscript::bootstrap::standard_library { }), "front"); - m.add(fun(static_cast(&ContainerType::push_front)), [&]() -> std::string { - if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { - m.eval("# Pushes the second value onto the front of container while making a clone of the value\n" - "def push_front(" - + type - + " container, x)\n" - "{ \n" - " if (x.is_var_return_value()) {\n" - " x.reset_var_return_value() \n" - " container.push_front_ref(x) \n" - " } else { \n" - " container.push_front_ref(clone(x)); \n" - " }\n" - "} \n"); - return "push_front_ref"; - } else { - return "push_front"; - } - }()); + if constexpr (std::is_copy_constructible_v) { + m.add(fun(static_cast(&ContainerType::push_front)), [&]() -> std::string { + if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { + m.eval("# Pushes the second value onto the front of container while making a clone of the value\n" + "def push_front(" + + type + + " container, x)\n" + "{ \n" + " if (x.is_var_return_value()) {\n" + " x.reset_var_return_value() \n" + " container.push_front_ref(x) \n" + " } else { \n" + " container.push_front_ref(clone(x)); \n" + " }\n" + "} \n"); + return "push_front_ref"; + } else { + return "push_front"; + } + }()); + } m.add(fun(static_cast(&ContainerType::pop_front)), "pop_front"); } diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index c4094da1..0a2d252b 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1437,6 +1437,31 @@ TEST_CASE("Issue #421 - Switch with type_conversion does not compare destroyed o })") == 0); } +// Issue #524: A std::vector of std::unique_ptrs can't be added +// vector_type should compile with non-copyable value types by +// skipping copy-dependent operations via if constexpr. +struct Issue524_Foo { + int value = 42; +}; + +TEST_CASE("Issue #524 - vector of unique_ptr can be registered") { + using VecType = std::vector>; + + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser()); + + // This should compile and not throw - previously failed to compile + // because vector_type tried to instantiate copy constructor, assignment, + // push_back(const T&), insert_at(const T&), and resize(n, const T&) + // for the non-copyable std::unique_ptr. + chaiscript::ModulePtr m = std::make_shared(); + chaiscript::bootstrap::standard_library::vector_type("UniqueVec", *m); + CHECK_NOTHROW(chai.add(m)); + + // Verify basic operations still work + CHECK(chai.eval("var v = UniqueVec(); v.size()") == 0); + CHECK(chai.eval("var v2 = UniqueVec(); v2.empty()") == true); +} + // Issue #625: function_less_than comparator must satisfy strict-weak ordering. // Registering overloaded functions with different arities triggered a // std::stable_sort assertion on macOS 15.2 (hardened libc++) because the