Boost.Python return a list of noncopyable objects
Question: I have a type `X` that is noncopyable and I want to expose a function that
creates a `list` of them:

    
    
    #include <boost/python.hpp>
    
    namespace py = boost::python;
    
    struct X {
        X(int i) : i(i) { }
        X(const X& ) = delete;
        X& operator=(X const&) = delete;
    
        int i;
        friend std::ostream& operator<<(std::ostream& os, X const& x) {
            return os << "X(" << x.i << ")";
        }
    };
    
    py::list get_xs(int n) {
        py::list xs;
        for (int i = 0; i < n; ++i) {
            xs.append(X{i});
        }
        return xs;
    }
    
    BOOST_PYTHON_MODULE(Foo)
    {
        py::class_<X, boost::noncopyable>("X", py::init<int>())
            .def(str(py::self))
            .def(repr(py::self))
        ;
    
        py::def("get_xs", get_xs);
    }
    

This compiles fine, yet when I try to use it, gives me the dreaded:

    
    
    >>> import Foo
    >>> Foo.get_xs(10)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: No to_python (by-value) converter found for C++ type: X
    

What does that error actually mean? How do I fix it?


Answer: `noncopyable` looks to be the problem. When `X` is copyable then everything is
fine.

If `X` must be `noncopyable` then `boost::shared_ptr` can be used:

    
    
    py::list get_xs(int n) {
        py::list xs;
        for (int i = 0; i < n; ++i) {
            xs.append(boost::shared_ptr<X>(new X(i)));
        }
        return xs;
    }
    
    ....
    
    BOOST_PYTHON_MODULE(Foo)
    {
        py::class_<X, boost::shared_ptr<X>, boost::noncopyable>("X", py::init<int>())
        ...
        ...
    
        py::register_ptr_to_python<boost::shared_ptr<X>>();
    }
    

