Topic: Problem Summary: template specialization on function types
Author: "Garth A. Dickie" <Garth_Dickie@avid.com>
Date: 1999/04/20 Raw View
Summary of a problem which cannot be solved within the current language:
(Other people have pointed this out. I'm just looking to start more
discussion of the problem.)
The current template mechanism does not deal well with function types
where the number of arguments to the function is not known. We either
have a generic type, or a type which specifies the number of arguments:
// generic
template< class FunctionT >
void DoSomethingWithAFunction( FunctionT f );
// a partial specialization of the above:
template< class Arg1T, class Arg2T >
void DoSomethingWithAFunction( void ( * f )( Arg1T, Arg2T ));
// a partial specialization for a member function:
template< class T, class Arg1T, class Arg2T >
void DoSomethingWithAFunction( void ( T::* f )( Arg1T, Arg2T ));
It is impossible to write a template which manipulates the arguments
of a function without placing a restriction on the number of arguments.
The usual workaround is to define specializations up to some fixed maximum
number of arguments. This requires that we write and maintain redundant
code. I don't like this solution.
Some concrete examples:
1) I would like bind< 3 >( f, 12 ) to mean "bind the 3rd argument
to f to the value 12". Following the definition of bind2nd, the helper function
bind would look like:
template< int whichI, typename FunctionT, typename ArgT >
binder< whichI, FunctionT > bind( FunctionT const & f, ArgT const & arg )
{
return binder< whichI, FunctionT >( f, arg );
}
However, there is no generic way to define the class binder.
2) In a gasket between Python and C++ I wrote a generic "register"
function which makes a member function available to the Python environment:
template< class T >
class ScriptableReferenceObject
{
public:
template< class FunctionT >
static void Register( char const * name, FunctionT const & f );
};
This function is used in a very simple way:
class A : public ScriptableReferenceObject< A >
{
public:
int foo( char const * s, double g ) const;
void bar( );
static void RegisterMembers( )
{
Register( "foo", foo );
Register( "bar", bar );
}
};
Hidden behind this interface, however, is an enormous mess of partial specializations.
These handle static member vs. non-const member vs. const member functions,
void vs. non-void return types, and argument counts from 0 to N. (N is currently 8).
Some of the specialized functions from the implementation might look like:
template< class T >
class GenericMemberFunction
{
public:
PythonResult operator( )( T & object, PythonArguments const & argumentList );
};
template< class T, class Arg1T, class Arg2T, class ResultT >
class GenericMemberFunction2WithResult
: public GenericMemberFunction
{
public:
GenericMemberFunction2WithResult( ResultT ( T::* f )( Arg1T, Arg2T ))
: mMemberFunctionPointer( f )
{
}
PythonResult operator( )( T & object, PythonArguments const & argumentList )
{
CheckArgumentCount( argumentList, 2 );
ResultT typedResult = ( object.* mMemberFunctionPointer )(
ExtractArgument< Arg1T >( argumentList, 0 ),
ExtractArgument< Arg2T >( argumentList, 1 ));
return PythonResult( typedResult );
}
}
template< class T >
class ScriptableReferenceObject
{
private:
void RegisterGeneric( char const * name, GenericFunctionBase const * function );
template< class T, class Arg1T, class Arg2T, class ResultT >
void RegisterInternal( char const * name, ResultT ( T::* f )( Arg1T, Arg2T ))
{
RegisterGeneric( name, new GenericFunction2< T, Arg1T, Arg2T, ResultT >( function ));
}
}
The challenge is to find a natural, simple syntax which lets us write about lists
of function arguments and lists of argument types. We want to replace the
two-argument specializations above with generic N-argument specializations.
Any suggestions?
Regards,
Garth
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]