From 6020ba44bb31f88c7f6483e03799b78f7861636f Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 11:53:39 +0200 Subject: [PATCH 1/7] Move EmptyPythonVisitor to its own header file --- CMakeLists.txt | 10 +++++++--- include/eigenpy/std-vector.hpp | 7 +------ include/eigenpy/utils/empty-visitor.hpp | 11 +++++++++++ 3 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 include/eigenpy/utils/empty-visitor.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ed103c432..030a659cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,9 +170,12 @@ endif(BUILD_WITH_ACCELERATE_SUPPORT) # --- INCLUDE ---------------------------------------- # ---------------------------------------------------- set(${PROJECT_NAME}_UTILS_HEADERS - include/eigenpy/utils/scalar-name.hpp include/eigenpy/utils/is-approx.hpp - include/eigenpy/utils/is-aligned.hpp include/eigenpy/utils/traits.hpp - include/eigenpy/utils/python-compat.hpp) + include/eigenpy/utils/scalar-name.hpp + include/eigenpy/utils/is-approx.hpp + include/eigenpy/utils/is-aligned.hpp + include/eigenpy/utils/traits.hpp + include/eigenpy/utils/python-compat.hpp + include/eigenpy/utils/empty-visitor.hpp) set(${PROJECT_NAME}_SOLVERS_HEADERS include/eigenpy/solvers/solvers.hpp @@ -250,6 +253,7 @@ set(${PROJECT_NAME}_HEADERS include/eigenpy/numpy-map.hpp include/eigenpy/geometry.hpp include/eigenpy/geometry-conversion.hpp + include/eigenpy/map.hpp include/eigenpy/memory.hpp include/eigenpy/numpy.hpp include/eigenpy/numpy-allocator.hpp diff --git a/include/eigenpy/std-vector.hpp b/include/eigenpy/std-vector.hpp index bcef20c85..08850a8d7 100644 --- a/include/eigenpy/std-vector.hpp +++ b/include/eigenpy/std-vector.hpp @@ -21,6 +21,7 @@ #include "eigenpy/eigen-to-python.hpp" #include "eigenpy/pickle-vector.hpp" #include "eigenpy/registration.hpp" +#include "eigenpy/utils/empty-visitor.hpp" namespace eigenpy { // Forward declaration @@ -396,12 +397,6 @@ createExposeStdMethodToStdVector(const CoVisitor &co_visitor) { } // namespace internal -struct EmptyPythonVisitor - : public ::boost::python::def_visitor { - template - void visit(classT &) const {} -}; - namespace internal { template struct def_pickle_std_vector { diff --git a/include/eigenpy/utils/empty-visitor.hpp b/include/eigenpy/utils/empty-visitor.hpp new file mode 100644 index 000000000..e8c035ad9 --- /dev/null +++ b/include/eigenpy/utils/empty-visitor.hpp @@ -0,0 +1,11 @@ +#include "eigenpy/fwd.hpp" + +namespace eigenpy { + +struct EmptyPythonVisitor + : public ::boost::python::def_visitor { + template + void visit(classT &) const {} +}; + +} // namespace eigenpy From 2a92f7f6514b22c1882779853a10c4eca5302cb3 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 12:46:59 +0200 Subject: [PATCH 2/7] Map enhancements: split GenericMapPythonVisitor into its own file map.hpp, add visitor arg to ::expose() with overloads --- CHANGELOG.md | 9 + include/eigenpy/map.hpp | 251 ++++++++++++++++++++++++ include/eigenpy/std-map.hpp | 231 +--------------------- include/eigenpy/utils/empty-visitor.hpp | 2 +- unittest/python/test_std_map.py | 10 +- unittest/std_map.cpp | 9 +- 6 files changed, 286 insertions(+), 226 deletions(-) create mode 100644 include/eigenpy/map.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 291eac761..1a572ad55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Added + +- `GenericMapPythonVisitor`/`StdMapPythonVisitor` can now take an extra visitor argument in the `expose()` method, similar to `StdVectorPythonVisitor` + +### Changed + +- Move `GenericMapPythonVisitor` to its own header `eigenpy/map.hpp` +- Move `EmptyPythonVisitor` to new header `eigenpy/utils/empty-visitor.hpp` + ## [3.9.1] - 2024-09-19 ### Added diff --git a/include/eigenpy/map.hpp b/include/eigenpy/map.hpp new file mode 100644 index 000000000..6931ea52b --- /dev/null +++ b/include/eigenpy/map.hpp @@ -0,0 +1,251 @@ +/// Copyright (c) 2016-2024 CNRS INRIA +/// This file was originally taken from Pinocchio (header +/// ) +/// + +#ifndef __eigenpy_map_hpp__ +#define __eigenpy_map_hpp__ + +#include "eigenpy/pickle-vector.hpp" +#include "eigenpy/registration.hpp" +#include "eigenpy/utils/empty-visitor.hpp" + +#include +#include +#include + +namespace eigenpy { +namespace details { + +/// \brief Change the behavior of indexing (method __getitem__ in Python). +/// This is suitable e.g. for container of Eigen matrix objects if you want to +/// mutate them. +/// \sa overload_base_get_item_for_std_vector +template +struct overload_base_get_item_for_std_map + : public boost::python::def_visitor< + overload_base_get_item_for_std_map > { + typedef typename Container::value_type value_type; + typedef typename Container::value_type::second_type data_type; + typedef typename Container::key_type key_type; + typedef typename Container::key_type index_type; + + template + void visit(Class& cl) const { + cl.def("__getitem__", &base_get_item); + } + + private: + static boost::python::object base_get_item( + boost::python::back_reference container, PyObject* i_) { + index_type idx = convert_index(container.get(), i_); + typename Container::iterator i = container.get().find(idx); + if (i == container.get().end()) { + PyErr_SetString(PyExc_KeyError, "Invalid key"); + boost::python::throw_error_already_set(); + } + + typename boost::python::to_python_indirect< + data_type&, boost::python::detail::make_reference_holder> + convert; + return boost::python::object(boost::python::handle<>(convert(i->second))); + } + + static index_type convert_index(Container& /*container*/, PyObject* i_) { + boost::python::extract i(i_); + if (i.check()) { + return i(); + } else { + boost::python::extract i(i_); + if (i.check()) return i(); + } + + PyErr_SetString(PyExc_TypeError, "Invalid index type"); + boost::python::throw_error_already_set(); + return index_type(); + } +}; + +} // namespace details + +/////////////////////////////////////////////////////////////////////////////// +// The following snippet of code has been taken from the header +// https://github.com/loco-3d/crocoddyl/blob/v2.1.0/bindings/python/crocoddyl/utils/map-converter.hpp +// The Crocoddyl library is written by Carlos Mastalli, Nicolas Mansard and +// Rohan Budhiraja. +/////////////////////////////////////////////////////////////////////////////// + +namespace bp = boost::python; + +/** + * @brief Create a pickle interface for the std::map + * + * @param[in] Container Map type to be pickled + * \sa Pickle + */ +template +struct PickleMap : public PickleVector { + static void setstate(bp::object op, bp::tuple tup) { + Container& o = bp::extract(op)(); + bp::stl_input_iterator begin(tup[0]), end; + o.insert(begin, end); + } +}; + +/// Conversion from dict to map solution proposed in +/// https://stackoverflow.com/questions/6116345/boostpython-possible-to-automatically-convert-from-dict-stdmap +/// This template encapsulates the conversion machinery. +template +struct dict_to_map { + static void register_converter() { + bp::converter::registry::push_back(&dict_to_map::convertible, + &dict_to_map::construct, + bp::type_id()); + } + + /// Check if conversion is possible + static void* convertible(PyObject* object) { + // Check if it is a list + if (!PyObject_GetIter(object)) return 0; + return object; + } + + /// Perform the conversion + static void construct(PyObject* object, + bp::converter::rvalue_from_python_stage1_data* data) { + // convert the PyObject pointed to by `object` to a bp::dict + bp::handle<> handle(bp::borrowed(object)); // "smart ptr" + bp::dict dict(handle); + + // get a pointer to memory into which we construct the map + // this is provided by the Python runtime + typedef bp::converter::rvalue_from_python_storage storage_type; + void* storage = reinterpret_cast(data)->storage.bytes; + + // placement-new allocate the result + new (storage) Container(); + + // iterate over the dictionary `dict`, fill up the map `map` + Container& map(*(static_cast(storage))); + bp::list keys(dict.keys()); + int keycount(static_cast(bp::len(keys))); + for (int i = 0; i < keycount; ++i) { + // get the key + bp::object keyobj(keys[i]); + bp::extract keyproxy(keyobj); + if (!keyproxy.check()) { + PyErr_SetString(PyExc_KeyError, "Bad key type"); + bp::throw_error_already_set(); + } + typename Container::key_type key = keyproxy(); + + // get the corresponding value + bp::object valobj(dict[keyobj]); + bp::extract valproxy(valobj); + if (!valproxy.check()) { + PyErr_SetString(PyExc_ValueError, "Bad value type"); + bp::throw_error_already_set(); + } + typename Container::mapped_type val = valproxy(); + map.emplace(key, val); + } + + // remember the location for later + data->convertible = storage; + } + + static bp::dict todict(Container& self) { + bp::dict dict; + typename Container::const_iterator it; + for (it = self.begin(); it != self.end(); ++it) { + dict.setdefault(it->first, it->second); + } + return dict; + } +}; + +/// Policies which handle the non-default constructible case +/// and set_item() using emplace(). +template +struct emplace_set_derived_policies + : bp::map_indexing_suite< + Container, NoProxy, + emplace_set_derived_policies > { + typedef typename Container::key_type index_type; + typedef typename Container::value_type::second_type data_type; + typedef typename Container::value_type value_type; + using DerivedPolicies = + bp::detail::final_map_derived_policies; + + template + static void extension_def(Class& cl) { + // Wrap the map's element (value_type) + std::string elem_name = "map_indexing_suite_"; + bp::object class_name(cl.attr("__name__")); + bp::extract class_name_extractor(class_name); + elem_name += class_name_extractor(); + elem_name += "_entry"; + namespace mpl = boost::mpl; + + typedef typename mpl::if_< + mpl::and_, mpl::bool_ >, + bp::return_internal_reference<>, bp::default_call_policies>::type + get_data_return_policy; + + bp::class_(elem_name.c_str(), bp::no_init) + .def("__repr__", &DerivedPolicies::print_elem) + .def("data", &DerivedPolicies::get_data, get_data_return_policy()) + .def("key", &DerivedPolicies::get_key); + } + + static void set_item(Container& container, index_type i, data_type const& v) { + container.emplace(i, v); + } +}; + +/** + * @brief Expose the map-like container, e.g. (std::map). + * + * @param[in] Container Container to expose. + * @param[in] NoProxy When set to false, the elements will be copied when + * returned to Python. + */ +template +struct GenericMapVisitor + : public emplace_set_derived_policies, + public dict_to_map { + typedef dict_to_map FromPythonDictConverter; + + template + static void expose(const std::string& class_name, + const std::string& doc_string, + const bp::def_visitor& visitor) { + namespace bp = bp; + + if (!register_symbolic_link_to_registered_type()) { + bp::class_(class_name.c_str(), doc_string.c_str()) + .def(GenericMapVisitor()) + .def("todict", &FromPythonDictConverter::todict, bp::arg("self"), + "Returns the map type as a Python dictionary.") + .def_pickle(PickleMap()) + .def(visitor); + // Register conversion + FromPythonDictConverter::register_converter(); + } + } + + static void expose(const std::string& class_name, + const std::string& doc_string = "") { + expose(class_name, doc_string, EmptyPythonVisitor()); + } + + template + static void expose(const std::string& class_name, + const bp::def_visitor& visitor) { + expose(class_name, "", visitor); + } +}; + +} // namespace eigenpy + +#endif // ifndef __eigenpy_map_hpp__ diff --git a/include/eigenpy/std-map.hpp b/include/eigenpy/std-map.hpp index 6640450f6..d4d719a9b 100644 --- a/include/eigenpy/std-map.hpp +++ b/include/eigenpy/std-map.hpp @@ -1,229 +1,14 @@ -/// Copyright (c) 2016-2022 CNRS INRIA -/// This file was taken from Pinocchio (header -/// ) +/// Copyright (c) 2024, INRIA /// -#ifndef __eigenpy_utils_map_hpp__ -#define __eigenpy_utils_map_hpp__ +#ifndef __eigenpy_std_map_hpp__ +#define __eigenpy_std_map_hpp__ -#include "eigenpy/pickle-vector.hpp" - -#include -#include -#include -#include +#include "eigenpy/map.hpp" +#include "eigenpy/deprecated.hpp" #include namespace eigenpy { -namespace details { -template -struct overload_base_get_item_for_std_map - : public boost::python::def_visitor< - overload_base_get_item_for_std_map > { - typedef typename Container::value_type value_type; - typedef typename Container::value_type::second_type data_type; - typedef typename Container::key_type key_type; - typedef typename Container::key_type index_type; - - template - void visit(Class& cl) const { - cl.def("__getitem__", &base_get_item); - } - - private: - static boost::python::object base_get_item( - boost::python::back_reference container, PyObject* i_) { - index_type idx = convert_index(container.get(), i_); - typename Container::iterator i = container.get().find(idx); - if (i == container.get().end()) { - PyErr_SetString(PyExc_KeyError, "Invalid key"); - boost::python::throw_error_already_set(); - } - - typename boost::python::to_python_indirect< - data_type&, boost::python::detail::make_reference_holder> - convert; - return boost::python::object(boost::python::handle<>(convert(i->second))); - } - - static index_type convert_index(Container& /*container*/, PyObject* i_) { - boost::python::extract i(i_); - if (i.check()) { - return i(); - } else { - boost::python::extract i(i_); - if (i.check()) return i(); - } - - PyErr_SetString(PyExc_TypeError, "Invalid index type"); - boost::python::throw_error_already_set(); - return index_type(); - } -}; - -} // namespace details - -/////////////////////////////////////////////////////////////////////////////// -// The following snippet of code has been taken from the header -// https://github.com/loco-3d/crocoddyl/blob/v2.1.0/bindings/python/crocoddyl/utils/map-converter.hpp -// The Crocoddyl library is written by Carlos Mastalli, Nicolas Mansard and -// Rohan Budhiraja. -/////////////////////////////////////////////////////////////////////////////// - -namespace bp = boost::python; - -/** - * @brief Create a pickle interface for the std::map - * - * @param[in] Container Map type to be pickled - * \sa Pickle - */ -template -struct PickleMap : public PickleVector { - static void setstate(bp::object op, bp::tuple tup) { - Container& o = bp::extract(op)(); - bp::stl_input_iterator begin(tup[0]), end; - o.insert(begin, end); - } -}; - -/// Conversion from dict to map solution proposed in -/// https://stackoverflow.com/questions/6116345/boostpython-possible-to-automatically-convert-from-dict-stdmap -/// This template encapsulates the conversion machinery. -template -struct dict_to_map { - static void register_converter() { - bp::converter::registry::push_back(&dict_to_map::convertible, - &dict_to_map::construct, - bp::type_id()); - } - - /// Check if conversion is possible - static void* convertible(PyObject* object) { - // Check if it is a list - if (!PyObject_GetIter(object)) return 0; - return object; - } - - /// Perform the conversion - static void construct(PyObject* object, - bp::converter::rvalue_from_python_stage1_data* data) { - // convert the PyObject pointed to by `object` to a bp::dict - bp::handle<> handle(bp::borrowed(object)); // "smart ptr" - bp::dict dict(handle); - - // get a pointer to memory into which we construct the map - // this is provided by the Python runtime - typedef bp::converter::rvalue_from_python_storage storage_type; - void* storage = reinterpret_cast(data)->storage.bytes; - - // placement-new allocate the result - new (storage) Container(); - - // iterate over the dictionary `dict`, fill up the map `map` - Container& map(*(static_cast(storage))); - bp::list keys(dict.keys()); - int keycount(static_cast(bp::len(keys))); - for (int i = 0; i < keycount; ++i) { - // get the key - bp::object keyobj(keys[i]); - bp::extract keyproxy(keyobj); - if (!keyproxy.check()) { - PyErr_SetString(PyExc_KeyError, "Bad key type"); - bp::throw_error_already_set(); - } - typename Container::key_type key = keyproxy(); - - // get the corresponding value - bp::object valobj(dict[keyobj]); - bp::extract valproxy(valobj); - if (!valproxy.check()) { - PyErr_SetString(PyExc_ValueError, "Bad value type"); - bp::throw_error_already_set(); - } - typename Container::mapped_type val = valproxy(); - map.emplace(key, val); - } - - // remember the location for later - data->convertible = storage; - } - - static bp::dict todict(Container& self) { - bp::dict dict; - typename Container::const_iterator it; - for (it = self.begin(); it != self.end(); ++it) { - dict.setdefault(it->first, it->second); - } - return dict; - } -}; - -/// Policies which handle the non-default constructible case -/// and set_item() using emplace(). -template -struct emplace_set_derived_policies - : bp::map_indexing_suite< - Container, NoProxy, - emplace_set_derived_policies > { - typedef typename Container::key_type index_type; - typedef typename Container::value_type::second_type data_type; - typedef typename Container::value_type value_type; - using DerivedPolicies = - bp::detail::final_map_derived_policies; - - template - static void extension_def(Class& cl) { - // Wrap the map's element (value_type) - std::string elem_name = "map_indexing_suite_"; - bp::object class_name(cl.attr("__name__")); - bp::extract class_name_extractor(class_name); - elem_name += class_name_extractor(); - elem_name += "_entry"; - namespace mpl = boost::mpl; - - typedef typename mpl::if_< - mpl::and_, mpl::bool_ >, - bp::return_internal_reference<>, bp::default_call_policies>::type - get_data_return_policy; - - bp::class_(elem_name.c_str(), bp::no_init) - .def("__repr__", &DerivedPolicies::print_elem) - .def("data", &DerivedPolicies::get_data, get_data_return_policy()) - .def("key", &DerivedPolicies::get_key); - } - - static void set_item(Container& container, index_type i, data_type const& v) { - container.emplace(i, v); - } -}; - -/** - * @brief Expose the map-like container, e.g. (std::map). - * - * @param[in] Container Container to expose. - * @param[in] NoProxy When set to false, the elements will be copied when - * returned to Python. - */ -template -struct GenericMapVisitor - : public emplace_set_derived_policies, - public dict_to_map { - typedef dict_to_map FromPythonDictConverter; - - static void expose(const std::string& class_name, - const std::string& doc_string = "") { - namespace bp = bp; - - bp::class_(class_name.c_str(), doc_string.c_str()) - .def(GenericMapVisitor()) - .def("todict", &FromPythonDictConverter::todict, bp::arg("self"), - "Returns the map type as a Python dictionary.") - .def_pickle(PickleMap()); - // Register conversion - FromPythonDictConverter::register_converter(); - } -}; /** * @brief Expose an std::map from a type given as template argument. @@ -242,9 +27,9 @@ struct StdMapPythonVisitor : GenericMapVisitor, NoProxy> {}; namespace python { -// fix previous mistake -using ::eigenpy::StdMapPythonVisitor; +// fix previous mistake (deprecated using-decl) +EIGENPY_DEPRECATED using ::eigenpy::StdMapPythonVisitor; } // namespace python } // namespace eigenpy -#endif // ifndef __eigenpy_utils_map_hpp__ +#endif // ifndef __eigenpy_std_map_hpp__ diff --git a/include/eigenpy/utils/empty-visitor.hpp b/include/eigenpy/utils/empty-visitor.hpp index e8c035ad9..64e55a774 100644 --- a/include/eigenpy/utils/empty-visitor.hpp +++ b/include/eigenpy/utils/empty-visitor.hpp @@ -1,4 +1,4 @@ -#include "eigenpy/fwd.hpp" +#include namespace eigenpy { diff --git a/unittest/python/test_std_map.py b/unittest/python/test_std_map.py index ea5711195..5df54053b 100644 --- a/unittest/python/test_std_map.py +++ b/unittest/python/test_std_map.py @@ -1,4 +1,4 @@ -from std_map import copy, copy_boost, std_map_to_dict +from std_map import X, copy, copy_boost, copy_X, std_map_to_dict t = {"one": 1.0, "two": 2.0} t2 = {"one": 1, "two": 2, "three": 3} @@ -7,3 +7,11 @@ assert std_map_to_dict(copy(t)) == t m = copy_boost(t2) assert m.todict() == t2 + +xmap_cpp = copy_X({"one": X(1), "two": X(2)}) +print(xmap_cpp.todict()) +x1 = xmap_cpp["one"] +x1.val = 11 +print(xmap_cpp.todict()) +assert xmap_cpp["one"].val == 11 +assert xmap_cpp["two"].val == 2 diff --git a/unittest/std_map.cpp b/unittest/std_map.cpp index ef641aad8..483861651 100644 --- a/unittest/std_map.cpp +++ b/unittest/std_map.cpp @@ -45,9 +45,16 @@ BOOST_PYTHON_MODULE(std_map) { eigenpy::GenericMapVisitor >::expose( "boost_map_int"); - eigenpy::GenericMapVisitor >::expose("StdMap_X"); + using StdMap_X = std::map; + bp::class_("X", bp::init()).def_readwrite("val", &X::val); + + // this just needs to compile + eigenpy::GenericMapVisitor::expose( + "StdMap_X", + eigenpy::details::overload_base_get_item_for_std_map()); bp::def("std_map_to_dict", std_map_to_dict); bp::def("copy", copy); bp::def("copy_boost", copy_boost); + bp::def("copy_X", +[](const StdMap_X& m) { return m; }); } From 997911a55db9eb373d0f4e04e60c2a5b8f9b0f4a Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 12:53:36 +0200 Subject: [PATCH 3/7] Rename overload_base_get_item_for_std_map to overload_base_get_item_for_map + move out of details namespace + keep details::overload_base_get_item_for_std_map symbol as a typedef, marked deprecated --- CHANGELOG.md | 1 + include/eigenpy/map.hpp | 15 +++++++++++---- unittest/std_map.cpp | 3 +-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a572ad55..04ff4aa1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed - Move `GenericMapPythonVisitor` to its own header `eigenpy/map.hpp` +- Rename `overload_base_get_item_for_std_map` to `overload_base_get_item_for_map`, move out of `eigenpy::details` namespace - Move `EmptyPythonVisitor` to new header `eigenpy/utils/empty-visitor.hpp` ## [3.9.1] - 2024-09-19 diff --git a/include/eigenpy/map.hpp b/include/eigenpy/map.hpp index 6931ea52b..743fe93f3 100644 --- a/include/eigenpy/map.hpp +++ b/include/eigenpy/map.hpp @@ -9,22 +9,22 @@ #include "eigenpy/pickle-vector.hpp" #include "eigenpy/registration.hpp" #include "eigenpy/utils/empty-visitor.hpp" +#include "eigenpy/deprecated.hpp" #include #include #include namespace eigenpy { -namespace details { /// \brief Change the behavior of indexing (method __getitem__ in Python). /// This is suitable e.g. for container of Eigen matrix objects if you want to /// mutate them. /// \sa overload_base_get_item_for_std_vector template -struct overload_base_get_item_for_std_map +struct overload_base_get_item_for_map : public boost::python::def_visitor< - overload_base_get_item_for_std_map > { + overload_base_get_item_for_map > { typedef typename Container::value_type value_type; typedef typename Container::value_type::second_type data_type; typedef typename Container::key_type key_type; @@ -66,6 +66,13 @@ struct overload_base_get_item_for_std_map } }; +namespace details { + +template +using overload_base_get_item_for_std_map EIGENPY_DEPRECATED_MESSAGE( + "Use overload_base_get_item_for_map<> instead.") = + overload_base_get_item_for_map; + } // namespace details /////////////////////////////////////////////////////////////////////////////// @@ -78,7 +85,7 @@ struct overload_base_get_item_for_std_map namespace bp = boost::python; /** - * @brief Create a pickle interface for the std::map + * @brief Create a pickle interface for the map type * * @param[in] Container Map type to be pickled * \sa Pickle diff --git a/unittest/std_map.cpp b/unittest/std_map.cpp index 483861651..6edc455b1 100644 --- a/unittest/std_map.cpp +++ b/unittest/std_map.cpp @@ -50,8 +50,7 @@ BOOST_PYTHON_MODULE(std_map) { // this just needs to compile eigenpy::GenericMapVisitor::expose( - "StdMap_X", - eigenpy::details::overload_base_get_item_for_std_map()); + "StdMap_X", eigenpy::overload_base_get_item_for_map()); bp::def("std_map_to_dict", std_map_to_dict); bp::def("copy", copy); From a81f79fbd35d59e2a028705bb42792dcccb70951 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 13:08:39 +0200 Subject: [PATCH 4/7] is this a fix --- include/eigenpy/std-map.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/eigenpy/std-map.hpp b/include/eigenpy/std-map.hpp index d4d719a9b..b7a4f36bb 100644 --- a/include/eigenpy/std-map.hpp +++ b/include/eigenpy/std-map.hpp @@ -28,7 +28,7 @@ struct StdMapPythonVisitor namespace python { // fix previous mistake (deprecated using-decl) -EIGENPY_DEPRECATED using ::eigenpy::StdMapPythonVisitor; +using ::eigenpy::StdMapPythonVisitor EIGENPY_DEPRECATED; } // namespace python } // namespace eigenpy From a99c268a31d938efb646759765957c74580a8e30 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 13:14:04 +0200 Subject: [PATCH 5/7] it was not a fix --- include/eigenpy/std-map.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/eigenpy/std-map.hpp b/include/eigenpy/std-map.hpp index b7a4f36bb..a4efd439b 100644 --- a/include/eigenpy/std-map.hpp +++ b/include/eigenpy/std-map.hpp @@ -27,8 +27,8 @@ struct StdMapPythonVisitor : GenericMapVisitor, NoProxy> {}; namespace python { -// fix previous mistake (deprecated using-decl) -using ::eigenpy::StdMapPythonVisitor EIGENPY_DEPRECATED; +// fix previous mistake +using ::eigenpy::StdMapPythonVisitor; } // namespace python } // namespace eigenpy From aa2c54b432ccba1c176844b111e4325d0cd79c19 Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Mon, 23 Sep 2024 13:35:46 +0200 Subject: [PATCH 6/7] add include guard for empty-visitor.hpp --- include/eigenpy/utils/empty-visitor.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/eigenpy/utils/empty-visitor.hpp b/include/eigenpy/utils/empty-visitor.hpp index 64e55a774..1c832500a 100644 --- a/include/eigenpy/utils/empty-visitor.hpp +++ b/include/eigenpy/utils/empty-visitor.hpp @@ -1,3 +1,6 @@ +#ifndef __eigenpy_utils_empty_visitor_hpp__ +#define __eigenpy_utils_empty_visitor_hpp__ + #include namespace eigenpy { @@ -9,3 +12,5 @@ struct EmptyPythonVisitor }; } // namespace eigenpy + +#endif // ifndef __eigenpy_utils_empty_visitor_hpp__ From e03f6b289f18cb3d0084363ec94be5a6646cbfdb Mon Sep 17 00:00:00 2001 From: ManifoldFR Date: Wed, 25 Sep 2024 17:45:06 +0200 Subject: [PATCH 7/7] Move overload_base_get_item_for_std_map<> using-typedef back to std-map.hpp --- include/eigenpy/map.hpp | 10 ---------- include/eigenpy/std-map.hpp | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/eigenpy/map.hpp b/include/eigenpy/map.hpp index 743fe93f3..b22bc8b23 100644 --- a/include/eigenpy/map.hpp +++ b/include/eigenpy/map.hpp @@ -9,7 +9,6 @@ #include "eigenpy/pickle-vector.hpp" #include "eigenpy/registration.hpp" #include "eigenpy/utils/empty-visitor.hpp" -#include "eigenpy/deprecated.hpp" #include #include @@ -66,15 +65,6 @@ struct overload_base_get_item_for_map } }; -namespace details { - -template -using overload_base_get_item_for_std_map EIGENPY_DEPRECATED_MESSAGE( - "Use overload_base_get_item_for_map<> instead.") = - overload_base_get_item_for_map; - -} // namespace details - /////////////////////////////////////////////////////////////////////////////// // The following snippet of code has been taken from the header // https://github.com/loco-3d/crocoddyl/blob/v2.1.0/bindings/python/crocoddyl/utils/map-converter.hpp diff --git a/include/eigenpy/std-map.hpp b/include/eigenpy/std-map.hpp index a4efd439b..a6aca840e 100644 --- a/include/eigenpy/std-map.hpp +++ b/include/eigenpy/std-map.hpp @@ -10,6 +10,15 @@ namespace eigenpy { +template +using overload_base_get_item_for_std_map EIGENPY_DEPRECATED_MESSAGE( + "Use overload_base_get_item_for_map<> instead.") = + overload_base_get_item_for_map; + +namespace details { +using ::eigenpy::overload_base_get_item_for_std_map; +} // namespace details + /** * @brief Expose an std::map from a type given as template argument. *