#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <iostream>
using namespace std;
template <typename T>
struct CallbackParamTraits
{
typedef const T& ForwardType;
typedef T StorageType;
};
// The Storage should almost be impossible to trigger unless someone manually
// specifies type of the bind parameters. However, in case they do,
// this will guard against us accidentally storing a reference parameter.
//
// The ForwardType should only be used for unbound arguments.
template <typename T>
struct CallbackParamTraits<T&>
{
typedef T& ForwardType;
typedef T StorageType;
};
// Note that for array types , we implicitly add a const in the conversion. This
// means that it is not possible to bind array arguments to functions that take
// a non-const pointer. Trying to specialize the template based on a "const
// T[n]" does not seem to match correctly, so we are stuck with this
// restriction.
template <typename T, size_t n>
struct CallbackParamTraits<T[n]>
{
typedef const T* ForwardType;
typedef const T* StorageType;
};
// See comment for CallbackParamTraits<T[n]>.
template <typename T>
struct CallbackParamTraits<T[]>
{
typedef const T* ForwardType;
typedef const T* StorageType;
};
template <typename T>
T& CallbackForward(T& t)
{
return t;
}
template <typename R>
class RunnableAdapter;
template <typename R>
class RunnableAdapter<R(*)()>
{
public:
typedef R (RunType)();
explicit RunnableAdapter(R(*function)())
: function_(function)
{
}
R Run()
{
return function_();
}
private:
R (*function_)();
};
// Function: Arity 1.
template <typename R, typename A1>
class RunnableAdapter<R(*)(A1)>
{
public:
typedef R (RunType)(A1);
explicit RunnableAdapter(R(*function)(A1))
: function_(function)
{
}
R Run(typename CallbackParamTraits<A1>::ForwardType a1)
{
return function_(CallbackForward(a1));
}
private:
R (*function_)(A1);
};
int test1( int i )
{
cout << "i is " << i << endl;
return 0;
}
int test2( int * pI )
{
cout << "i is " << *pI << endl;
return 0;
}
int test3( int& i )
{
cout << "i is " << i << endl;
return 0;
}
int test3( const int& i )
{
cout << "i is " << i << endl;
return 0;
}
int test3( int arr[3] )
{
cout << "i is " << arr[0] << endl;
return 0;
}
int test4( int arr[] )
{
cout << "i is " << arr[0] << endl;
return 0;
}
int main(int argc, char** argv)
{
int i = 23;
RunnableAdapter< int (*)( int ) > ra( test1 );
ra.Run( i );
RunnableAdapter< int (*)( int* ) > ra1( test2 );
ra1.Run( &i );
int pArr [ 3 ];
pArr[ 0 ] = 20;
RunnableAdapter< int (*)( int[3] ) > ra2( test4 );
ra2.Run( pArr );
RunnableAdapter< int (*)( int[] ) > ra3( test4 );
ra3.Run( pArr );
return 0;
}