Question

I made a finally simulator using lambda in C++11 as below:

#include <cstdio>

template<typename Functor>
struct Finalizer
{
    Finalizer(Functor& func) : func_(func) {} // (1)
    ~Finalizer() { func_(); }

private:
    Functor func_; // (2)
};

template<typename functor>
Finalizer<functor> finally(functor& func)
{
    return Finalizer<functor>(func); (3)
}

int main()
{
    int a = 20;

    // print the value of a at the escape of the scope
    auto finalizer = finally([&]{ printf("%d\n", a); }); // (4)
}

The code works as intended, but there is undesired copy ctor call (of lambda functor) at the ctor of Finalizer struct (1). (Thankfully, copy construction at the return statement in the finally function (3 -> 4) is avoided by RVO.)

Compiler does not eliminate the copy ctor call (at least in vc10 - gcc may optimize it), and if the type of the functor in Finalizer struct (2) is changed to reference it'll crash since the lambda argument at the finally call (4) is r-value.

Of course the code can be "optimized" like below

template<typename Functor>
struct Finalizer
{
    Finalizer(Functor& func) : func_(func) {}
    ~Finalizer() { func_(); }

private:
    Functor& func_;
};

int main()
{
    int a = 20;

    auto finalizer = [&]{ printf("%d\n", a); };
    Finalizer<decltype(finalizer)> fin(finalizer);
}

No overhead, only a printf call is placed at the end of scope. But... I don't like it. :( I tried to wrap it with macro, but it needs to declare two "name" - one for lambda object, the other for finalizer object.

My objective is simple -

  1. Every unnecessary performance overhead which can be avoided should be eliminated. Ideally, there should be no function call, every procedure should be inlined.
  2. Keep the concise expression as its purpose of utility function. Use of macro is allowed, but discouraged.

Is there any solution to avoid it for this situation?

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top