[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>
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to