|
||||
|
Section 33:
|
[33.14] Can you make functionoids faster than normal function calls?
Yes. If you have a small functionoid, and in the real world that's rather common, the cost of the function-call can be high compared to the cost of the work done by the functionoid. In the previous FAQ, functionoids were implemented using virtual functions and will typically cost you a function-call. An alternate approach uses templates. The following example is similar in spirit to the one in the previous FAQ. I have renamed doit() to operator()() to improve the caller code's readability and to allow someone to pass a regular function-pointer:
class Funct1 {
public:
Funct1(float y) : y_(y) { }
int operator()(int x) { ...code from funct1... }
private:
float y_;
};
class Funct2 {
public:
Funct2(std::string const& y, int z) : y_(y), z_(z) { }
int operator()(int x) { ...code from funct2... }
private:
std::string y_;
int z_;
};
class Funct3 {
public:
Funct3(const std::vector<double>& y) : y_(y) { }
int operator()(int x) { ...code from funct3... }
private:
std::vector<double> y_;
};
The difference between this approach and the one in the
previous FAQ is that the fuctionoid gets "bound" to the caller at
compile-time rather than at run-time. Think of it as passing in a parameter:
if you know at compile-time the kind of functionoid you ultimately want to
pass in, then you can use the above technique, and you can,
at least in typical cases, get a speed benefit
from having the compiler inline-expand the
functionoid code within the caller. Here is an example:
template <typename FunctObj>
void myCode(FunctObj f)
{
...
f(...args-go-here...);
...
}
When the compiler compiles the above, it might
inline-expand the call which might improve
performance.
Here is one way to call the above:
void blah()
{
...
Funct2 x("functionoids are powerful", 42);
myCode(x);
...
}
Aside: as was hinted at in the first paragraph above, you may also pass in the
names of normal functions (though you might incur the cost of the function
call when the caller uses these):
void myNormalFunction(int x);
void blah()
{
...
myCode(myNormalFunction);
...
}
|
|||