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

Alf P. Steinbach /Usenet alf.p.steinbach+usenet at gmail.com
Sat Jul 17 05:50:48 EDT 2010


[Cross-posted comp.lang.c++ and comp.lang.python]

Consider the following code, from an example usage of some C++ support for 
Python I'm working on, "cppy":


<code>
     struct Noddy
     {
         PyPtr       first;
         PyPtr       last;
         int         number;

         Noddy( PyWeakPtr pySelf, PyPtr args, PyPtr kwArgs )
             : number( 0 )
         {
             // ... some initialization here
         }

         PyPtr name()
         {
             return (PyString( first ) + L" " + PyString( last )).pyPtr();
         }
     };

     struct NoddyPyClass: PyClass< Noddy >
     {
         typedef PyClass< Noddy >    Base;

         NoddyPyClass( PyModule& m, PyString const& name, PyString const& doc )
             : Base( m, name, doc,
                 Exposition()
                     .method(
                         L"name",        CPPY_METHOD_FORWARDER( name ),
                         L"Return the name, combining the first and last name"
                         )
                     .attribute(
                         L"first",       CPPY_GETSET_FORWARDERS( first ),
                         L"first name"
                         )
                     .attribute(
                         L"last",        CPPY_GETSET_FORWARDERS( last ),
                         L"last name"
                         )
                     .attribute(
                         L"number",      CPPY_GETSET_FORWARDERS( number ),
                         L"noddy number"
                         )
                 )
         {}
     };
</code>


Originally e.g.

     CPPY_GETSET_FORWARDERS( number ),

had to be written as

     CPPY_GETSET_FORWARDERS( int, number ),

because in order to use a compile time member pointer as template actual 
argument, one needs to supply the member type as a separate template argument.

E.g. the template might look like

     template< class Class, class MemberType, MemberType Class::*pMember >
     struct ForwardersForGetAndSet
     {
         // Some definitions here, hardwiring that compile time member pointer!
     };

Apparently there was no way around the user repeating explicitly the member type 
that the compiler already knew about... It seemed akin to deducing the return 
type of a function. Difficult in C++98 (although Boost does a fair job).

But then it seemed that I'm not totally senile yet, for 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.

He he.

Perhaps this trick is well-known already, but it was new to me, so! :-)


Cheers,

- Alf

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



More information about the Python-list mailing list