diff --git a/CHANGELOG.md b/CHANGELOG.md
index 264fe6f7c427835ebe76b1b6358f3d4c28c8ee4c..14daba352c16a917b5c4de492e5608afc21c7585 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,8 +7,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 ## [Unreleased]
 
 ### Added
+
+- Add more general visitor `GenericMapPythonVisitor` for map types test `boost::unordered_map<std::string, int>` ([#504](https://github.com/stack-of-tasks/eigenpy/pull/504))
+- Support for non-[default-contructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible) types in map types ([#504](https://github.com/stack-of-tasks/eigenpy/pull/504))
 - Add type_info helpers ([#502](https://github.com/stack-of-tasks/eigenpy/pull/502))
 
+### Changed
+
+- Move `StdMapPythonVisitor` out of `eigenpy::python` namespace, which was a mistake ([#504](https://github.com/stack-of-tasks/eigenpy/pull/504))
+
 ## [3.9.0] - 2024-08-31
 
 ### Changed
diff --git a/README.md b/README.md
index 53d120ce14f8d050e6b34eaa7ef02b3fc0b16f9c..ce57bc0bbc544de06a10bd7fcdacab5110aa420e 100644
--- a/README.md
+++ b/README.md
@@ -14,15 +14,16 @@ EigenPy — Versatile and efficient Python bindings between Numpy and Eigen
 **EigenPy** is an open-source framework that allows the binding of the famous [Eigen](http://eigen.tuxfamily.org) C++ library in Python via Boost.Python.
 
 **EigenPy** provides:
- - full memory sharing between Numpy and Eigen, avoiding memory allocation
- - full support Eigen::Ref avoiding memory allocation
- - full support of the Eigen::Tensor module
- - exposition of the Geometry module of Eigen for easy code prototyping
- - standard matrix decomposion routines of Eigen such as the Cholesky decomposition (SVD and QR decompositions [can be added](#contributing))
- - full support of SWIG objects
- - full support of runtime declaration of Numpy scalar types
- - extended API to expose std::vector types
- - full support of vectorization between C++ and Python (all the hold objects are properly aligned in memory)
+
+- full memory sharing between Numpy and Eigen, avoiding memory allocation
+- full support Eigen::Ref avoiding memory allocation
+- full support of the Eigen::Tensor module
+- exposition of the Geometry module of Eigen for easy code prototyping
+- standard matrix decomposion routines of Eigen such as the Cholesky decomposition (SVD and QR decompositions [can be added](#contributing))
+- full support of SWIG objects
+- full support of runtime declaration of Numpy scalar types
+- extended API to expose several STL types and some of their Boost equivalents: `optional` types, `std::pair`, maps, variants...
+- full support of vectorization between C++ and Python (all the hold objects are properly aligned in memory)
 
 ## Setup
 
diff --git a/include/eigenpy/std-map.hpp b/include/eigenpy/std-map.hpp
index 0d7123577b1a337f5aefe7fd372b6c8ec8209385..6640450f686fdf8bacd227545bc2c8e65aba174b 100644
--- a/include/eigenpy/std-map.hpp
+++ b/include/eigenpy/std-map.hpp
@@ -70,8 +70,6 @@ struct overload_base_get_item_for_std_map
 // Rohan Budhiraja.
 ///////////////////////////////////////////////////////////////////////////////
 
-namespace python {
-
 namespace bp = boost::python;
 
 /**
@@ -144,7 +142,7 @@ struct dict_to_map {
         bp::throw_error_already_set();
       }
       typename Container::mapped_type val = valproxy();
-      map[key] = val;
+      map.emplace(key, val);
     }
 
     // remember the location for later
@@ -161,24 +159,56 @@ struct dict_to_map {
   }
 };
 
+/// Policies which handle the non-default constructible case
+/// and set_item() using emplace().
+template <class Container, bool NoProxy>
+struct emplace_set_derived_policies
+    : bp::map_indexing_suite<
+          Container, NoProxy,
+          emplace_set_derived_policies<Container, NoProxy> > {
+  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<Container, NoProxy>;
+
+  template <class Class>
+  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<std::string> class_name_extractor(class_name);
+    elem_name += class_name_extractor();
+    elem_name += "_entry";
+    namespace mpl = boost::mpl;
+
+    typedef typename mpl::if_<
+        mpl::and_<boost::is_class<data_type>, mpl::bool_<!NoProxy> >,
+        bp::return_internal_reference<>, bp::default_call_policies>::type
+        get_data_return_policy;
+
+    bp::class_<value_type>(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 an std::map from a type given as template argument.
+ * @brief Expose the map-like container, e.g. (std::map).
  *
- * @param[in] T          Type to expose as std::map<T>.
- * @param[in] Compare    Type for the Compare in std::map<T,Compare,Allocator>.
- * @param[in] Allocator  Type for the Allocator in
- * std::map<T,Compare,Allocator>.
+ * @param[in] Container  Container to expose.
  * @param[in] NoProxy    When set to false, the elements will be copied when
  * returned to Python.
  */
-template <class Key, class T, class Compare = std::less<Key>,
-          class Allocator = std::allocator<std::pair<const Key, T> >,
-          bool NoProxy = false>
-struct StdMapPythonVisitor
-    : public bp::map_indexing_suite<
-          typename std::map<Key, T, Compare, Allocator>, NoProxy>,
-      public dict_to_map<std::map<Key, T, Compare, Allocator> > {
-  typedef std::map<Key, T, Compare, Allocator> Container;
+template <class Container, bool NoProxy = false>
+struct GenericMapVisitor
+    : public emplace_set_derived_policies<Container, NoProxy>,
+      public dict_to_map<Container> {
   typedef dict_to_map<Container> FromPythonDictConverter;
 
   static void expose(const std::string& class_name,
@@ -186,15 +216,34 @@ struct StdMapPythonVisitor
     namespace bp = bp;
 
     bp::class_<Container>(class_name.c_str(), doc_string.c_str())
-        .def(StdMapPythonVisitor())
+        .def(GenericMapVisitor())
         .def("todict", &FromPythonDictConverter::todict, bp::arg("self"),
-             "Returns the std::map as a Python dictionary.")
+             "Returns the map type as a Python dictionary.")
         .def_pickle(PickleMap<Container>());
     // Register conversion
     FromPythonDictConverter::register_converter();
   }
 };
 
+/**
+ * @brief Expose an std::map from a type given as template argument.
+ *
+ * @param[in] T          Type to expose as std::map<T>.
+ * @param[in] Compare    Type for the Compare in std::map<T,Compare,Allocator>.
+ * @param[in] Allocator  Type for the Allocator in
+ * std::map<T,Compare,Allocator>.
+ * @param[in] NoProxy    When set to false, the elements will be copied when
+ * returned to Python.
+ */
+template <class Key, class T, class Compare = std::less<Key>,
+          class Allocator = std::allocator<std::pair<const Key, T> >,
+          bool NoProxy = false>
+struct StdMapPythonVisitor
+    : GenericMapVisitor<std::map<Key, T, Compare, Allocator>, NoProxy> {};
+
+namespace python {
+// fix previous mistake
+using ::eigenpy::StdMapPythonVisitor;
 }  // namespace python
 }  // namespace eigenpy
 
diff --git a/unittest/python/test_std_map.py b/unittest/python/test_std_map.py
index 091027b21b063eb3cfe0e33659a5fc7e96096943..ea57111952e3ed7c84027217250a64b902966298 100644
--- a/unittest/python/test_std_map.py
+++ b/unittest/python/test_std_map.py
@@ -1,6 +1,9 @@
-from std_map import copy, std_map_to_dict
+from std_map import copy, copy_boost, std_map_to_dict
 
 t = {"one": 1.0, "two": 2.0}
+t2 = {"one": 1, "two": 2, "three": 3}
 
 assert std_map_to_dict(t) == t
 assert std_map_to_dict(copy(t)) == t
+m = copy_boost(t2)
+assert m.todict() == t2
diff --git a/unittest/std_map.cpp b/unittest/std_map.cpp
index 5997e39cc82df6deb68ceb355e3613c2cb122b83..ef641aad861c92d796d385f5f60d7cedc0017af9 100644
--- a/unittest/std_map.cpp
+++ b/unittest/std_map.cpp
@@ -3,7 +3,7 @@
 
 #include <eigenpy/eigenpy.hpp>
 #include <eigenpy/std-map.hpp>
-#include <iostream>
+#include <boost/unordered_map.hpp>
 
 namespace bp = boost::python;
 
@@ -22,14 +22,32 @@ std::map<std::string, T1> copy(const std::map<std::string, T1>& map) {
   return out;
 }
 
+template <typename T1>
+boost::unordered_map<std::string, T1> copy_boost(
+    const boost::unordered_map<std::string, T1>& obj) {
+  return obj;
+}
+
+struct X {
+  X() = delete;
+  X(int x) : val(x) {}
+  int val;
+};
+
 BOOST_PYTHON_MODULE(std_map) {
   eigenpy::enableEigenPy();
 
-  eigenpy::python::StdMapPythonVisitor<
+  eigenpy::StdMapPythonVisitor<
       std::string, double, std::less<std::string>,
       std::allocator<std::pair<const std::string, double> >,
       true>::expose("StdMap_Double");
 
+  eigenpy::GenericMapVisitor<boost::unordered_map<std::string, int> >::expose(
+      "boost_map_int");
+
+  eigenpy::GenericMapVisitor<std::map<std::string, X> >::expose("StdMap_X");
+
   bp::def("std_map_to_dict", std_map_to_dict<double>);
   bp::def("copy", copy<double>);
+  bp::def("copy_boost", copy_boost<int>);
 }