I am putting together a "simple" template class. It offers an interface for performing some operations on a database, so there are other members as well (primarily for operating on the container member). However, for our purposes, the template class looks something like this:
template<typename T, //the type of objects the class will be manipulating
typename S> //the signature of the function the class will be using
FunctionHandler
{
private:
std::vector<T> container;
boost::function<S> the_operation;
SomeClass* pSC; //a database connection; implementation unimportant
//some other members--not relevant here
public:
boost::function<???> Operate;
FunctionHandler(boost::function<S> the_operation_)
: the_operation(the_operation_)
{
Operate = boost::bind(the_operation, pSC, std::back_inserter<std::vector<T> >,
/*infer that all other parameters passed to Operate
should be passed through to the_operation*/);
}
//other peripheral functions
}
My question is two-fold.
Operate
. i.e. what replaces ???
boost::bind
that it should pass any other parameters given to Operate
on to the_operation
? In other words, for some arbitrary function signature S
that looks like void (SomeClass*, std::back_insert_iterator<std::vector<T> >, int, bool)
and some other arbitrary function signature O
that looks like void (SomeClass*, std::back_insert_iterator<std::vector<T> >, double, double, bool)
how do I write this template class such that Operate
has a signature of void (int, bool)
for the first and void (double, double, bool)
for the second, and passes its values on to the_operation
's 3rd-Nth parameters?In my searches I couldn't find any questions quite like this one.
Why even use bind? We can get the same effect without it. I'm using Iter
as a template but you can fill it in with whater the right type is:
template <typename S, typename Iter>
class Operator
{
boost::function<S> func_;
SomeClass* cls_;
Iter iter_;
public:
Operator(function<S> func, SomeClass* cls, Iter iter)
: func_(func), cls_(cls), iter_(iter)
{ }
// one for each # of args
typename boost::result_of<
boost::function<S>(SomeClass*, Iter)
>::type operator()() const {
return func_(cls_, iter_);
}
template <typename A>
typename boost::result_of<
boost::function<S>(SomeClass*, Iter, A)
>::type operator()(A a) const {
return func_(cls_, iter_, a);
}
template <typename A, typename B>
typename boost::result_of<
boost::function<S>(SomeClass*, Iter, A, B)
>::type operator()(A a, B b) const {
return func_(cls_, iter_, a, b);
}
// etc.
};
We're making all of the operator()
s, but they'll only get instantiated if they get called - so as long as you call the right one (which for any solution, you'll have to anyway), this works.