Sharing: member type deduction for member pointers (Alf's device?)

Alf P. Steinbach /Usenet alf.p.steinbach+usenet at gmail.com
Sat Jul 17 09:02:58 EDT 2010


* Alf P. Steinbach /Usenet, on 17.07.2010 11:50:
> [Cross-posted comp.lang.c++ and comp.lang.python]
>
> [snip]
> this occurred to me:
>
>      #define CPPY_GETSET_FORWARDERS( name )                          \
>          ::progrock::cppy::forwardersGetSet(                         \
>              &CppClass::name                                         \
>              ).themForwarders< &CppClass::name >()
>
> Here forwardersGetSet is a templated function that via argument type
> deduction produces an instance of a templated struct, thereby "knowing"
> the member type, which struct in turn has a member function templated on
> the member pointer, which the macro supplies *twice*, once as run-time
> arg and once as compile-time.

That trick allowed uniform treatment of data and function member pointers. :-)

So, with cppy the complete noddy2 example from the docs (I'm sort of working my 
way through the Python doc examples) now looks as shown below.

The "typelessness" of the 'first' and 'last' members is in order to recreate as 
close as possible the noddy2 functionality, or, lack of it. Also, I haven't got 
around to sort of backporting the 'Exposition' scheme to modules. So, exposure 
of module functionality looks a little different from same for types, for now.


<code>
// The Python 3.1.1 docs' Noddy 2 example rewritten using cppy.
// Docs: "Extending and Embedding the Python Interpreter" §2.1.1

#include <progrock/cppy/PyClass.h>      // PyWeakPtr, PyPtr, PyModule, PyClass
using namespace progrock;

namespace {
     using namespace cppy;

     struct Noddy
     {
         PyPtr       first;
         PyPtr       last;
         int         number;

         Noddy( PyWeakPtr pySelf, PyPtr args, PyPtr kwArgs )
             : number( 0 )
         {
             devsupport::suppressUnusedWarning( pySelf );

             PyWeakPtr   pFirstName  = 0;
             PyWeakPtr   pLastName   = 0;

             static char*    kwlist[] = { "first", "last", "number", 0 };

             ::PyArg_ParseTupleAndKeywords(
                 args.rawPtr(), kwArgs.rawPtr(), "|OOi", kwlist,
                 pointerTo( pFirstName ), pointerTo( pLastName ), &number
                 )
                 >> Accept< IsNonZero >()
                 || throwX( "Invalid args" );

             if( pFirstName != 0 )   { first = pFirstName; }
             if( pLastName != 0 )    { last = pLastName; }
         }

         PyPtr name()
         {
             (first != 0)
                 || throwX( ::PyExc_AttributeError, "first" );
             (last != 0)
                 || throwX( ::PyExc_AttributeError, "last" );
             return (PyString( first ) + L" " + PyString( last )).pyPtr();
         }
     };

     struct NoddyPyClass: PyClass< Noddy >
     {
         NoddyPyClass( PyModule& m, PyString const& name, PyString const& doc )
             : PyClass< Noddy >( m, name, doc, Exposition()
                 .method(
                     L"name",    CPPY_GLUE( name ),
                     L"Return the name, combining the first and last name"
                     )
                 .attribute(
                     L"first",   CPPY_GLUE( first ),     L"first name"
                     )
                 .attribute(
                     L"last",    CPPY_GLUE( last ),      L"last name"
                     )
                 .attribute(
                     L"number",  CPPY_GLUE( number ),    L"noddy number"
                     )
                 )
         {}
     };

     class NoddyModule: public PyModule
     {
     private:
         NoddyPyClass    noddyPyClass_;

     public:
         NoddyModule()
             : PyModule(
                 L"noddy2", L"Example module that creates an extension type." )
             , noddyPyClass_( *this,
                 L"Noddy", L"A Noddy object has a name and a noddy number" )
         {}
     };
}    // namespace <anon>


PyMODINIT_FUNC
PyInit_noddy2()
{
     return cppy::safeInit< NoddyModule >();
}
</code>


I wonder if this is readable / self-documenting, or not?


Cheers,

- Alf

-- 
blog at <url: http://alfps.wordpress.com>



More information about the Python-list mailing list