Я сделал симулятор finally с использованием лямбда-выражения в C ++ 11, как показано ниже:
#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)
}
код работает, как задумано, но есть нежелательный вызов ctor копирования (лямбда-функтора) в ctor структуры Finalizer struct (1). (К счастью, RVO избегает конструкции копирования в операторе return в функции finally (3 -> 4).)
Компилятор не устраняет вызов copy ctor (по крайней мере, в vc10 - gcc может его оптимизировать), и если тип функтора в Finalizer struct (2) будет изменен на ссылку, он будет сбой, поскольку лямбда-аргумент в вызове finally (4) имеет значение r.
Конечно, код можно «оптимизировать», как показано ниже.
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);
}
Никаких накладных расходов, только вызов printf помещается в конец области видимости. Но ... мне это не нравится. :( Я пытался обернуть его макросом, но он должен объявить два «имени» - одно для лямбда-объекта, другое для объекта-финализатора.
Моя цель проста -
Есть ли какое-либо решение для избежать этого в этой ситуации?