Reputation: 23102
If I have a function which is required to produce a hook from an input object, should I try to do that without casting to std::function
? With these 2 options, which should I pick and is option 2 a meaningful improvement?
std::function<void()> CreateHook(std::function<void()> f)
{
return []()
{
return Hook(f);
};
}
// option 1:
void Hook(std::function<void()> f)
{
// do something
}
// option 2:
<typename F>
void Hook(F f)
{
// do something
}
Upvotes: 1
Views: 117
Reputation: 275800
Type erase only when you need to. Either:
template<class F>
std::function<void()> CreateHook(F f) { return []() { return Hook(f); }; }
or even in C++1y:
template<class F>
auto CreateHook(F f) { return [f=std::move(f)]() { return Hook(f); }; }
but the second is probably overkill (the f=std::move(f)
is not, but auto
is, as I am guessing you will just store the return value in a std::function
anyhow).
And if your Hook
function is simple and stable:
template <typename F> void Hook(F f) {
// do something
}
but if it is large and complex:
void Hook(std::function<void()> f) {
// do something
}
because it lets you split interface from implementation.
The downside to this strategy is that some compilers suck at eliminating identical code in different functions causing binary size bloat, and it can cause some compile time bloat.
But if you defer type erasure in both cases, you can eliminate both two virtual
function calls, and allow the compiler to inline the passed in f
within the Hook
body.
If however the interface for CreateHook
cannot be changed, and Hook
is only called from it, the template
version of Hook
is pointless, as it is only called with a std::function
anyhow.
Upvotes: 3
Reputation: 97661
In your example the template is pointless, because it is only ever instantiated for T = std::function<void()>
- the template overload is chosen by static type of f
, not the runtime type.
Upvotes: 3