[C++-SIG] some progress: CXX_Objects.h

Paul F. Dubois dubois1 at llnl.gov
Wed Jan 7 20:14:20 CET 1998


This is the second part of a message about my recent work.

//----------------------------------*-C++-*---------------------------------
-//
// Copyright 1996 The Regents of the University of California.
// All rights reserved.
//--------------------------------------------------------------------------
-//
#ifndef __CXX_Objects__h
#define __CXX_Objects__h
#include "Python.h"
#include "CXX_Exception.h"
#include <iostream>
#include <string>
using namespace std;
namespace Py {

    // Macro for assertion checking
#define Require(something) \
    {if(!(something)) throw PyException (#something);}

    // Forward declarations
    class Object;
    class Type;
    class Float;
    class Int;
    class Sequence;
    class String;
    class Tuple;
    class List;
    class Mapping;
    class Dict;
    // new_reference_to
    PyObject* new_reference_to (const Object& g); // return an owned
reference to the object g owns.
    PyObject* new_reference_to (PyObject* p);  // return an owned reference
to *p

    // Py_Null is a PyObject* (0) for signalling error returns
#define Py_Null (static_cast<PyObject*>(0))
    // Nothing is what a non-function returns
#define Nothing new_reference_to(Py_None)

    class FromAPI {
    // Python API routines return to you owned pointers.
    // FromAPI is a helper class to let you construct an object from one of
these.
    // Usage: Object(FromAPI(p)) or Object x = FromAPI(p)
    // where p is an already-owned pointer such as returned by an API
routine.
    private:
        PyObject *p;
        FromAPI& operator=(const FromAPI& other); // no assignment
        FromAPI(const FromAPI& other); // no copy constructor
    public:
        explicit FromAPI(PyObject *powned) { // construct from a pointer you
own, only!
            p = powned;
        }
        virtual ~FromAPI() {
            Py_XDECREF(p); // we own it, so kill it
        }
        operator PyObject*() {return p;}
    };


//==========================================================================
=//
    // class Object
    // The purpose of this class is to serve as the most general kind of
    // Python object, for the purpose of writing C++ extensions in Python
    // Objects hold a PyObject* which they own. This pointer is always a
    // valid pointer to a Python object. In children we must maintain this
behavior.
    //
    // Instructions on how to make your own class MyType descended from
Object:
    // (0) Pick a base class, either Object or perhaps Sequence or Mapping.
    //     This example assumes Object.

    // (1) Write a routine int MyType_Check (PyObject *) modeled after
PyInt_Check,
    //     PyFloat_Check, etc.

    // (2) Add method accepts:
    //     virtual bool accepts (PyObject *pyob) const {
    //         return pyob && MyType_Check (pyob);
    //     }

    // (3) Include the following constructor and copy constructor
    //                                                                   |
    //     explicit MyType (PyObject *pyob): Object(pyob) {
    //        validate();
    //     }
    //     MyType(const MyType& other): Object(other) {
    //        validate();
    //     }
    // You may wish to add other constructors; see the classes below for
examples.
    // Each constructor must end by validating the pointer you have created.

    // (4) Each class needs at least these two assignment operators:
    //  MyType& operator= (const Object& rhs) {
    //    return (*this = *rhs);
    //   }

    //   Mytype& operator= (const PyObject* rhsp) {
    //    if(*this == rhsp) return *this;
    //    set(rhsp);
    //    return *this;
    //   }

    // Object equality means they contain the same PyObject*
    int operator==(const Object& o1, const Object& o2);
    int operator==(const Object& o1, const PyObject *p2);
    int operator==(const PyObject *p1, const Object& o2);
    int operator!=(const Object& o1, const Object& o2);
    int operator!=(const Object& o1, const PyObject *p2);
    int operator!=(const PyObject *p1, const Object& o2);


    class Object {
    protected:
        PyObject* p; // the pointer to the Python object

        void set (const PyObject* pyob) {
            release();
            p = const_cast<PyObject *>(pyob);
            Py_XINCREF (p);
            validate();
        }

        void release () {
            Require((p==Py_Null) || (reference_count() > 0));
            Py_XDECREF (p);
            p = Py_Null;
        }

        void validate() {
            // release pointer if not the right type
            if (! accepts (p)) {
                release ();
                if(PyErr_Occurred()) { // Error message already set
                    throw PyException();
                }
                string s("Error creating object of type ");
                s += (typeid (*this)).name();
                throw PyException_TypeError (s.c_str());
            }
        }
        // Constructs an illegal object; child has to fix this fast!
        Object (): p(Py_Null) {}

    public:
        // Note on accepts: constructors call the base class
        // version of a virtual when calling the base class constructor,
        // so the test has to be done
        // explicitly in a descendent. Not so for the assignment operator.

        // Constructors acquire new ownership of pointer
        explicit Object (PyObject* pyob): p (pyob) {
            Py_XINCREF (p);
            validate();
        }

        // Copy constructor acquires new ownership of pointer
        Object (const Object& ob): p(*ob) {
            Py_XINCREF (p);
            validate();
        }

        // Assignment acquires new ownership of pointer
        Object& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Object& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }

        // Destructor
        virtual ~Object () {
            release ();
        }

        // Loaning the pointer to others, retain ownership
        PyObject* operator* () const

            return p;
        }

        PyObject* pointer () const {
            return p;
        }
        //
        // Queries
        //
        // Can pyob be used in this object's constructor?
        virtual bool accepts (PyObject *pyob) const {
            return (pyob != Py_Null);
        }

        int reference_count () const { // the reference count
            return p ? p->ob_refcnt : 0;
        }

        Type type () const; // the type object associated with this one

        String str () const; // the str() representation

        String repr () const; // the repr () representation

        int hasAttr (const char *s) const {
            return PyObject_HasAttrString (p,  const_cast<char*>(s));
        }

        Object getAttr (const char *s) const {
            return Object(FromAPI(
                PyObject_GetAttrString (p, const_cast<char*> (s))
                ));
        }

        Object getItem (const Object& key) const {
            return Object(FromAPI(PyObject_GetItem(p, *key)));
        }

        long hashValue () const {
            return PyObject_Hash (p);
        }

        // int print (FILE* fp, int flags=Py_Print_RAW) {
        //     return PyObject_Print (p, fp, flags);
        // }

        int isCallable () const {
            return PyCallable_Check (p);
        }

        int isMapping () const {
            return PyMapping_Check (p);
        }

        int isNumeric () const {
            return PyNumber_Check (p);
        }

        int isSequence () const {
            return PySequence_Check (p);
        }

        int isTrue () const {
            return PyObject_IsTrue (p);
        }

        int isType (const Type& t) const;

        int isTuple() const {
            return PyTuple_Check(p);
        }


        // Commands
        void setAttr (const char* attr_name, const Object& value) {
            if(PyObject_SetAttrString (p, const_cast<char*>(attr_name),
                *value) == -1)
                throw PyException_AttributeError ("getAttr failed.");
        }

        void delAttr (char *s) {
            if(PyObject_DelAttrString (p, s) == -1)
                throw PyException_AttributeError ("delAttr failed.");
        }

        void setItem (const Object& key, const Object& value) {
            if(PyObject_SetItem(p, *key, *value) == -1)
                throw PyException_KeyError("setItem failed.");
        }

        void delItem (const Object& key) {
            if(PyObject_DelItem(p, *key) == -1)
                throw PyException_KeyError("delItem failed.");
        }

    };
    // End of class Object

    ostream& operator<< (ostream& os, const Object& ob);

    // Class Type
    class Type: public Object {
    public:
        explicit Type (PyObject* pyob): Object(pyob) {
            validate();
        }

        explicit Type (const Object& ob): Object(*ob) {
            validate();
        }

        Type(const Type& t): Object(t) {
            validate();
        }

        Type& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Type& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyType_Check (pyob);
        }
    };

    // ===============================================
    // class Int
    class Int: public Object {
    public:
        // Constructor
        explicit Int (PyObject *pyob): Object (pyob) {
            validate();
        }

        Int (const Int& ob): Object(*ob) {
            validate();
        }
        // create from long
        explicit Int (long v = 0L): Object(FromAPI(PyInt_FromLong(v))) {
            validate();
        }

        // create from int
        explicit Int (int v) {
            long w = v;
            p = PyInt_FromLong(w);
            validate();
        }

        explicit Int (const Object& ob): Object() {
            p = PyNumber_Int(*ob);
            validate();
        }

        // Assignment acquires new ownership of pointer

        Int& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Int& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (FromAPI(PyNumber_Int(const_cast<PyObject*>(rhsp))));
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyInt_Check (pyob);
        }
        // convert to long
        operator long() const {
            return PyInt_AsLong (p);
        }
        // assign from an int
        Int& operator= (int v) {
            *this = FromAPI(PyInt_FromLong (long(v)));
            return *this;
        }
        // assign from long
        Int& operator= (long v) {
            *this = FromAPI(PyInt_FromLong (v));
            return *this;
        }
    };

    // ===============================================
    // class Long
    class Long: public Object {
    public:
        // Constructor
        explicit Long (PyObject *pyob): Object (pyob) {
            validate();
        }
        Long (const Long& ob): Object(*ob) {
            validate();
        }

        // create from long
        explicit Long (long v = 0L): Object(FromAPI(PyLong_FromLong(v))) {
            validate();
        }
        // create from int
        explicit Long (int v) {
            long w = v;
            p = PyLong_FromLong(w);
            validate();
        }

        // try to create from any object
        explicit Long (const Object& ob): Object() {
            p = PyNumber_Long(*ob);
            validate();
        }

        // Assignment acquires new ownership of pointer

        Long& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Long& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (FromAPI(PyNumber_Long(const_cast<PyObject*>(rhsp))));
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyLong_Check (pyob);
        }
        // convert to long
        operator long() const {
            return PyLong_AsLong (p);
        }
        operator double() const {
            return PyLong_AsDouble (p);
        }
        // assign from an int
        Long& operator= (int v) {
            *this = FromAPI(PyLong_FromLong (long(v)));
            return *this;
        }
        // assign from long
        Long& operator= (long v) {
            *this = FromAPI(PyLong_FromLong (v));
            return *this;
        }
    };

    // ===============================================
    // class Float
    // No constructor from a double since it is bad to overload on a pointer
    // and a numerical type.
    class Float: public Object {
    public:
        // Constructor
        explicit Float (PyObject *pyob): Object(pyob) {
            validate();
        }

        Float (const Float& f): Object(f) {
            validate();
        }
        // make from double
        explicit Float (double v=0.0) {
            p = PyFloat_FromDouble (v);
            validate();
        }

        // try to make from any object
        explicit Float (const Object& ob): Object() {
            p = PyNumber_Float(*ob);
            validate();
        }

        Float& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Float& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (FromAPI(PyNumber_Float(const_cast<PyObject*>(rhsp))));
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyFloat_Check (pyob);
        }
        // convert to double
        operator double () const {
            return PyFloat_AsDouble (p);
        }
        // assign from a double
        Float& operator= (double v) {
            *this = FromAPI(PyFloat_FromDouble (v));
            return *this;
        }
        // assign from an int
        Float& operator= (int v) {
            *this = FromAPI(PyFloat_FromDouble (double(v)));
            return *this;
        }
        // assign from long
        Float& operator= (long v) {
            *this = FromAPI(PyFloat_FromDouble (double(v)));
            return *this;
        }
        // assign from an Int
        Float& operator= (const Int& iob) {
            *this = FromAPI(PyFloat_FromDouble (double(long(iob))));
            return *this;
        }
    };

    // class Sequence
    // ...the base class for all sequence types

    class Sequence: public Object {
    protected:
        explicit Sequence (): Object() {}

    public:
        // Items are the result of the [] and *iterator operations
        class Item

        protected:
            Sequence* s; // the sequence
            int offset; // item number

        public:
            Item (Sequence* seq, int i)
                : s(seq), offset(i) {};

            ~Item() {}

            operator Object() const {
                return s->getItem (offset);
            }

            Item& operator=(const Item& rhs) { //lvalue
                s->setItem(offset, Object(rhs));
                return *this;
            }

            Item& operator=(Object ob){ // lvalue
                s->setItem(offset, ob);
                return *this;
            }
        }; // end of Item

        class iterator;

        explicit Sequence (PyObject* pyob): Object(pyob) {
            validate();
        }

        Sequence (const Sequence& ob): Object(ob) {
            validate();
        }

        // Assignment acquires new ownership of pointer

        Sequence& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Sequence& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }

        virtual bool accepts (PyObject *pyob) const {
            return pyob && PySequence_Check (pyob);
        }

        int length () const {
            return PySequence_Length (p);
        }

        // Element access
        const Item operator[](int index) const {
            return Item(const_cast<Sequence*>(this), index);
        }

        Item operator[](int index) {
            return Item(const_cast<Sequence*>(this), index);
        }

        virtual Object getItem (int i) const {
            return Object(FromAPI(PySequence_GetItem (p, i)));
        }

        virtual void setItem (int i, const Object& ob) {
            if (PySequence_SetItem (p, i, *ob) == -1) {
                throw PyException();
            }
        }

        Sequence repeat (int count) const {
            Require (count >= 0);
            return Sequence (FromAPI (PySequence_Repeat (p, count)));
        }

        Sequence concat (const Sequence& other) const {
            return Sequence (FromAPI (PySequence_Concat(p, *other)));
        }

        class iterator {
        protected:
            Sequence* seq;
            int count;

            iterator (Sequence* s, int where):
            seq(s), count(where) {}
        public:
            ~iterator () {}

            bool operator!= (const iterator& other) {
                return (seq != other.seq) || (count != other.count);
            }

            Item operator*() { return Item(seq, count);}

            // prefix ++
            iterator& operator++ () { count++; return *this;}
            // postfix ++
            const iterator operator++ (int) { return iterator(seq,
count++);}
            // prefix --
            iterator& operator-- () { count--; return *this;}
            // postfix --
            const iterator operator-- (int) { return iterator(seq,
count--);}
        };    // end of class Sequence::iterator

        iterator begin () const {
            return iterator(const_cast<Sequence*>(this), 0);
        }

        iterator end () const {
            return iterator(const_cast<Sequence*>(this), length());
        }
    };
    // ==================================================
    // class String
    class String: public Sequence {
    public:
        virtual void setItem (int offset, PyObject* pitem) {
            throw PyException("Cannot assign to a String element.");
        }

        explicit String (PyObject *pyob): Sequence (pyob) {
            validate();
        }
        String (const String& ob): Sequence(ob) {
            validate();
        }
        // Create from CString
        String (const char *v = ""): Sequence(){
            p = PyString_FromString (const_cast<char *> (v));
            validate();
        }

        String (const char *v, int vsize): Sequence() {
            p = PyString_FromStringAndSize (const_cast<char *>(v), vsize);
            validate();
        }
        // Assignment acquires new ownership of pointer

        String& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        String& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyString_Check (pyob);
        }
        // Convert to C string
        operator char* () const {
            return PyString_AsString (p);
        }
        // Assignment from C string
        String& operator= (const char *v) {
            *this = FromAPI(PyString_FromString (const_cast<char *> (v)));
            return *this;
        }
        // Append to present string
        void operator+= (const Sequence& s) {
            *this = concat(s);
        }
        void operator+= (const char* cs) {
            *this = concat(String(cs));
        }
        // Replicate present string
        void operator*= (int n) {
            Require(n > 0);
            *this = repeat(n);
        }
        // Queries
        int size () const { // same as length as far as I know?
            return PyString_Size (p);
        }
    };

    // ==================================================
    // class Tuple
    class Tuple: public Sequence {
    public:
        virtual void setItem (int offset, const Object&ob) {
            // note PyTuple_SetItem is a thief...
            if(PyTuple_SetItem (p, offset, new_reference_to(ob)) == -1) {
                throw PyException();
            }
        }

        // Constructor
        explicit Tuple (PyObject *pyob): Sequence (pyob) {
            validate();
        }

        Tuple (const Tuple& ob): Sequence(ob) {
            validate();
        }

        // New tuple of a given size
        explicit Tuple (int size = 0): Sequence() {
            p = PyTuple_New (size);
            validate ();
            for (int i=0; i < size; i++) {
                if(PyTuple_SetItem (p, i, new_reference_to(Py_None)) == -1)
{
                    throw PyException();
                }
            }
        }
        // Tuple from any sequence
        explicit Tuple (const Sequence& s)

            p = PyTuple_New (s.length());
            validate();
            for(int i=0; i < s.length(); i++) {
                if(PyTuple_SetItem (p, i, new_reference_to(s[i])) == -1) {
                    throw PyException();
                }
            }
        }
        // Assignment acquires new ownership of pointer

        Tuple& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Tuple& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyTuple_Check (pyob);
        }

        Tuple getSlice (int i, int j) const {
            return Tuple (FromAPI(PySequence_GetSlice (p, i, j)));
        }

    };

    // ==================================================
    // class List

    class List: public Sequence

    public:
        // Constructor
        explicit List (PyObject *pyob): Sequence(pyob) {
            validate();
        }
        List (const List& ob): Sequence(ob) {
            validate();
        }
        // Creation at a fixed size
        List (int size = 0): Sequence() {
            p = PyList_New (size);
            validate();
            for (int i=0; i < size; i++) {
                if(PyList_SetItem (p, i, new_reference_to(Py_None)) == -1) {
                    throw PyException();
                }
            }
        }

        // List from a sequence
        List (const Sequence& s): Sequence() {
            int n = s.length();
            p = PyList_New (n);
            validate();
            for (int i=0; i < n; i++) {
                if(PyList_SetItem (p, i, new_reference_to(s[i])) == -1) {
                    throw PyException();
                }
            }
        }

        // Assignment acquires new ownership of pointer

        List& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        List& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyList_Check (pyob);
        }

        List getSlice (int i, int j) const {
            return List (FromAPI(PyList_GetSlice (p, i, j)));
        }

        void setSlice (int i, int j, const Object& v) {
            if(PyList_SetSlice (p, i, j, *v) == -1) {
                throw PyException();
            }
        }

        void append (const Object& ob) {
            if(PyList_Append (p, *ob) == -1) {
                throw PyException();
            }
        }

        void insert (int i, const Object& ob) {
            if(PyList_Insert (p, i, *ob) == -1) {
                throw PyException();
            }
        }

        void sort () {
            if(PyList_Sort(p) == -1) {
                throw PyException();
            }
        }

        void reverse () {
            if(PyList_Reverse(p) == -1) {
                throw PyException();
            }
        }
    };
    // class Mapping
    // ==================================================
    class Mapping: public Object {
    protected:
        explicit Mapping(): Object() {
        }
    public:
        // MappingItem: proxy class for implementing []
        class MappingItem

        private:
            Mapping& s;
            const char *key;
        public:
            MappingItem (Mapping& seq, const char *k)
                : s(seq), key(k) {};
            MappingItem& operator=(const MappingItem& rhs); //lvalue
            MappingItem& operator=(Object ob); // lvalue
            operator Object() const;  // rvalue
        }; // end of MappingItem

        // Constructor
        explicit Mapping (PyObject *pyob): Object(pyob) {
            validate();
        }

        Mapping (const Mapping& ob): Object(ob) {
            validate();
        }
        // Assignment acquires new ownership of pointer

        Mapping& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Mapping& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyMapping_Check(pyob);
        }

        // Clear -- PyMapping Clear is missing
        //

        void clear () {
            List k = keys();
            for(List::iterator i = k.begin(); i != k.end(); i++) {
                delItem(*i);
            }
        }

        // Element Access
        const MappingItem operator[](const char* key) const;

        MappingItem operator[](const char* key);

        int length () const {
            return PyMapping_Length (p);
        }

        int hasKey (const char* s) const {
            Require(s != 0);
            return PyMapping_HasKeyString (p,
                const_cast<char*> (s));
        }

        Object getItem (const char* s) const {
            Require (s != 0);
            return Object(
                FromAPI(
                PyMapping_GetItemString (p,const_cast<char*> (s))
                )
                );
        }

        void setItem (const char* s, const Object& ob) {
            if (PyMapping_SetItemString (p, const_cast<char*> (s), *ob)
                == -1){
                throw PyException();
            }
        }

        void delItem (const char* s) {
            Require (s != 0);
            if (PyMapping_DelItemString (p, const_cast<char*> (s)) == -1){
                throw PyException();
            }
        }

        void delItem (const Object& s) {
            if (PyMapping_DelItem (p, *s) == -1){
                throw PyException();
            }
        }
        // Queries
        List keys () const {
            return List(FromAPI(PyMapping_Keys(p)));
        }

        List values () const { // each returned item is a (key, value) pair
            return List(FromAPI(PyMapping_Values(p)));
        }

        List items () const {
            return List(FromAPI(PyMapping_Items(p)));
        }
    };
    // ==================================================
    // class Dict
    class Dict: public Mapping {
    public:
        // Constructor
        explicit Dict (PyObject *pyob): Mapping (pyob) {
            validate();
        }
        Dict (const Dict& ob): Mapping(ob) {
            validate();
        }
        // Creation
        Dict (): Mapping() {
            p = PyDict_New ();
            validate();
        }
        // Assignment acquires new ownership of pointer

        Dict& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Dict& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set(rhsp);
            return *this;
        }
        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyDict_Check (pyob);
        }
    };

    class Callable: public Object {
    protected:
        explicit Callable (): Object() {}
    public:
        // Constructor
        explicit Callable (PyObject *pyob): Object (pyob) {
            validate();
        }

        Callable (const Callable& ob): Object(ob) {
            validate();
        }

        // Assignment acquires new ownership of pointer

        Callable& operator= (const Object& rhs) {
            return (*this = *rhs);
        }

        Callable& operator= (const PyObject* rhsp) {
            if(*this == rhsp) return *this;
            set (rhsp);
            return *this;
        }

        // Membership
        virtual bool accepts (PyObject *pyob) const {
            return pyob && PyCallable_Check (pyob);
        }

        // Call
        Object apply(const Tuple& args) const {
            return Object(FromAPI(PyObject_CallObject(p, *args)));
        }

        Object apply(PyObject* args = Py_Null) const {
            return Object(FromAPI(PyObject_CallObject(p, args)));
        }
    };
    Object operator+ (const Object& a);
    Object operator- (const Object& a);
    Object abs(const Object& a);
    pair<Object,Object> coerce (Object& a, Object& b);

    Object operator+ (const Object& a, const Object& b);
    Object operator+ (const Object& a, int j);
    Object operator+ (const Object& a, double v);
    Object operator+ (int j, const Object& b);
    Object operator+ (double v, const Object& b);

    Object operator- (const Object& a, const Object& b);
    Object operator- (const Object& a, int j);
    Object operator- (const Object& a, double v);
    Object operator- (int j, const Object& b);
    Object operator- (double v, const Object& b);
    Object operator* (const Object& a, const Object& b);
    Object operator* (const Object& a, int j);
    Object operator* (const Object& a, double v);
    Object operator* (int j, const Object& b);
    Object operator* (double v, const Object& b);
    Object operator/ (const Object& a, const Object& b);
    Object operator/ (const Object& a, int j);
    Object operator/ (const Object& a, double v);
    Object operator/ (int j, const Object& b);
    Object operator/ (double v, const Object& b);
    Object operator% (const Object& a, const Object& b);
    Object operator% (const Object& a, int j);
    Object operator% (const Object& a, double v);
    Object operator% (int j, const Object& b);
    Object operator% (double v, const Object& b);
} // end namespace Py
#endif // __CXX_Objects__h


_______________
C++-SIG - SIG for Development of a C++ Binding to Python

send messages to: c++-sig at python.org
administrivia to: c++-sig-request at python.org
_______________



More information about the Cplusplus-sig mailing list