Reputation: 220
I'm trying to write a generic wrapper in C++. Here is what I've written so far:
//primary template
template<typename T>
class function
{
};
//partially specialized template
template<typename T, typename U, typename V>
class wrapper<T(U,V)>
{
private:
//typedef pointer to function
typedef T (*pfn)(U,V);
pfn f;
public:
wrapper(pfn func):f(func)
{
};
T operator()(U a, V b)
{
return f(a,b);
}
};
Which can be instantiated using, for example:
wrapper<double(double, double)> someWrapper( &someFunction );
I was wondering if somebody could point me in the right direction in terms of how to modify the wrapper template to be able to instantiate in the following ways as well:
wrapper<double(double, double)> somewrapper( &someClass, &someClass::someFunction)
wrapper<double(someClass*, double)> somewrapper( &someClass::someFunction)
I'd appreciate any help in this.
Upvotes: 1
Views: 2269
Reputation: 81349
Use std::function
instead, or the Boost implementation if your compiler does not have TR1 yet. That said, this is the specialization you are looking for pointer to member functions:
template<typename T, typename C, typename U, typename V>
class wrapper<T (C::*)(U,V)>
{
private:
//typedef pointer to member-function
typedef T (C::*pfn)(U,V);
pfn f;
public:
wrapper(pfn func):f(func)
{
};
T operator()(C c, U a, V b)
{
return (c.*f)(a,b);
}
};
and its instantiate like this:
wrapper< double(someClass::*)(double, double) > somewrapper;
The first instantiation you gave is not impossible, but it needs a massive ammount of type erasure to get it to work, since the class type can't be deduced from the constructor argument.
wrapper<double(double, double)> somewrapper( &someClass, &someClass::someFunction)
The second one could be made to work, modifying my example code a bit, assuming you only want to instantiate it with pointer to member functions.
wrapper<double(someClass*, double)> somewrapper( &someClass::someFunction)
Assuming you want a single wrapper definition to be usable for both free and member functions with compatible arguments, you need again some type erasure to make it work. The implementation of Boost.Function
actually uses a different technique to avoid virtual
calls.
Upvotes: 2
Reputation: 10665
If you're doing this as a programming and learning exercise, then that's fine, but there are many viable alternatives that exist and are thoroughly tested. If using C++11 you can use std::function
, otherwise there's boost::function
and boost::bind
.
Now assuming this is a learning exercise, you will need to create versions of your wrapper for each number of different parameters and return values. You will also need to cover the cases where the function is a class member, and you might want to also deal with the case when you're dealing with a Functor class.
Suffice to say that this is a lot of work, lots of corner cases, just to duplicate something that already exists.
Upvotes: 2