[C++-sig] .def(str(self)) compile problems

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Sun Feb 20 14:24:52 CET 2005

--- Simon Burton <simon at arrowtheory.com> wrote:

> I'm having trouble getting the __str__ wrapper for my C++ class to compile.
> Everything else i've tried works fine (methods/functions/operators), but when
> I include the  .def( str(self) )
> line the compilation fails.

I am not sure, but I don't think Boost.Python supports what you want. I am not
even sure it could support automatic conversion from std::ostream to
std::string. However, I am sure you can get what you want in simple ways. For

- provide a function like this:

    interval_as_str(interval const& self)
      // conversion code here

- wrap like this:

    .def("__str__", interval_as_str)

Note that the unbound C++ interval_as_str() function is wrapped as a Python
member function.

Alternatively, if interval is your own class (as opposed to a class from a
third-party library) you could define a member function interval::as_str() and
wrap in the usual way:

    .def("__str__", &interval::as_str)

There is yet another alternative that I often prefer. From a practical
viewpoint it is often the simplest alternative, but I've seen people having a
hard time getting their mind around it. I'll try to explain anyway.

First consider a pure Python example:

    class point:
      def __init__(self, (x,y)):
        self.xy = (x,y)
    p = point((1,2))
    print p

The output is:

    <__main__.point instance at 0xb73f3f4c>

Now define this unbound function:
    def point_as_str(self):
      return str(self.xy)
    print point_as_str(p)

    (1, 2)

Almost what you want, but of course "print p" would be better than "print
point_as_str(p)". Here is the trick to make it work:
    point.__str__ = point_as_str
    print p

    (1, 2)

If you come from a C++ background this Python feature may seem surprising.
However, as David Abrahams once told me, the whole secret is that "Python is a
dynamic language."

To come back to your interval class: Simply remove the def(str(self) and inject
the __str__ method from Python:

    import lift

    def interval_as_str(self):
      return list(self.upper(self), self.lower(self))

    lift.interval.__str__ = interval_as_str


Do you Yahoo!? 
The all-new My Yahoo! - What will yours do?

More information about the Cplusplus-sig mailing list