quant
quant

Reputation: 23102

Should I avoid casting to std::function when passing lambdas as parameters?

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

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

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

Eric
Eric

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

Related Questions