views:

1100

answers:

1

Consider a template class like:

template<typename ReturnType, ReturnType Fn()>
class Proxy
{
    void run()
    {
     ReturnType ret = Fn();
     // ... do something ...
    }
};

// and a functions
int fn1() { return 5; }
float fn2() { return 5; }

This can be instantiated by using:

Proxy<int, &fn1> p1;

But explicitly declaring the return value type seems needless. What I am trying to achieve is something like:

 someProxyInstantation<&fn1> p1;
 someProxyInstantation<&fn2> p2;

Unfortunately, I'm no c++ expect and this seems like a hidden corner of the language (at least for me).

If I could just get from the pointer to the function to its type - something like: std::tr1::result_of<&fn>::type // Error 1 error C2923: 'std::tr1::result_of' : 'fn1' is not a valid template type argument for parameter '_Fty'

the error makes sense since the parameter is not a "type" at all

C++0x has the decltype(&fn1) but that is years away.

Any way of doing this in C++03 (+ tr1)?

Restrictions: - I don't want to pass the functor, f1 and f2 have to remain global functions that have a return value (can't move it to parameter).)

+5  A: 

This isn't possible in C++03. If you want to pass a function pointer as a non-type parameter, the compiler has to know the type of the parameter. So you have to provide the missing pieces (in this case, the return type). You can give the proxy the function pointer as a value at runtime, and provide it with the type of it as the only argument. Then you could write a generator function for you that does this job:

template<typename T>
Proxy<T> make_proxy(T t) { return Proxy<T>(t); }

Sadly, in current C++, you still have to give it the type in order to assign to a automatic variable:

Proxy<int(*)()> p = make_proxy(&fn1);

You can't use auto p = make_proxy(&fn1); yet. Note that if you want to use a function type on the left side, you have to change the generator function to provide not a function pointer type:

template<typename T>
Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) { 
    return Proxy<typename boost::remove_pointer<T>::type>(t); 
}

Now you can do

Proxy<int()> p = make_proxy(&fn1);

using the proxy, you can now just do

doSomething(make_proxy(&fn1));

And if doSomething is templated or otherwise polymorphic, it will not require you to know the exact type of the function.

Johannes Schaub - litb
Until c++0x this will have to do.
Hrvoje Prgeša