Reputation: 361
This was one of the questions showed up on my Final exam. I can't figure out what I'm supposed to do. I know BindSecArg requires a () operator, but not sure what goes inside.
In this question you are required to implement something similar to std::bind2nd. For simplicity main is written using a ”for”-loop, but it may be rewritten with ”for each” and STL containers.
class Functor1 {
public:
int operator()(const int & i, const int & j) const {
return i+j;
}
};
class Functor2 {
public:
int operator()(const int & i, const int & j) const {
return i*j;
}
};
template <typename T>
class BindSecArg
};
int main () {
Functor1 f1;
for (int i=0; i<10; ++i) std::cout << f1(i,i) << " "; //0 2 4 6 8 10
std::cout << std::endl;
Functor2 f2;
for (int i=0; i<10; ++i) std::cout << f2(i,i) << " "; //0 1 4 9 16 25
std::cout << std::endl;
BindSecArg<Functor1> b1(4); //bind second argument of Functor1 to 4
for (int i=0; i<10; ++i) std::cout << b1(i) << " "; //4 5 6 7 8 9
std::cout << std::endl;
BindSecArg<Functor2> b2(4); //bind second argument of Functor2 to 4
for (int i=0; i<10; ++i) std::cout << b2(i) << " "; //0 4 8 12 16 20
std::cout << std::endl;
}
Extra credit question: your implementation most probably doesn’t work (which is OK!) with
class Functor3 {
public:
std::string operator()(const std::string & i, const std::string & j) const {
return i+j;
}
};
how does STL solve this problem?
Upvotes: 1
Views: 574
Reputation: 61643
The operator()
for BindSecArg
needs to take one argument (obviously), and what it's supposed to do is call the operator()
from the "bound" functor, passing it (a) the passed-in "first" argument and (b) the "bound" second argument.
So we need to construct an instance of the bound functor's class (so that we can make that call), and we need to remember the second argument. We'll take care of both of these with data members.
That looks like:
template <typename T>
class BindSecArg
T toCall;
int second;
public:
// To initialize, we default-construct the bound-functor-instance, and copy the
// constructor parameter for our bound-parameter.
BindSecArg(int second): toCall(), second(second) {}
// To call, see the above discussion.
int operator() (int first) { return toCall(first, second); }
};
The standard library (please don't say "STL") bind2nd
addresses this by expecting T to be an "AdaptableBinaryFunction", i.e. to provide some typedef
members identifying the parameter and result types for operator()
, and then using these to inherit from a base class using those typedefs as template types, and then using typedefs provided by the base class to template its own operator()
implementation. These are some of the basic techniques of "template metaprogramming", and it gets complicated fast. You should look up some separate reading resources for this.
Upvotes: 3
Reputation: 17740
probably there are better implementations:
template <typename T>
class BindSecArg
{
public:
BindSecArg(int value2) : m_value2(value2){ };
int operator()(int value1) { return T()(value1, m_value2);}
private:
int m_value2;
};
int the link I posted in the comment to your question you can find the stl code.
Upvotes: 2
Reputation: 41351
Inside goes a call to Functor.operator(), passing the value given to BindSecArg
in its constructor as the second argument.
Upvotes: 0