Я сделал наконец симулятор с помощью лямбда в 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 из Finalizer struct (1). (К счастью, скопировать конструкцию на оператора возврата в функции наконец (3 -.> 4) избегают РВО)
Компилятор не исключает вызов копирования CTOR (по крайней мере, в VC10 - НКУ может оптимизировать его) , и если тип функтора в Finalizer struct (2) заменен на ссылку, он будет сбой, так как аргумент лямбда на , наконец, call (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 вызов помещается в конце объема. Но ... Мне это не нравится. :(Я попытался обернуть его с макросом, но для этого нужно объявить два «имя» -. Один для объекта лямбда, а другой для объекта финализатора
Моя цель проста -
- Каждый ненужный накладные расходы производительности которого можно избежать, должны быть устранены. в идеале, не должно быть никакого вызова функции, каждая процедура должна быть встраиваемыми.
- Держите краткое выражение в качестве своей цели функции полезности. Использование макрокоманды допускается, но не рекомендуется.
Есть ли солю чтобы избежать этого для этой ситуации?
По крайней мере, сказать 'шаблон <имяТипа функтор> Финалайзер наконец (функтор && FUNC) {вернуться Finalizer <имяТипа станд :: remove_reference :: тип> (станд :: вперед (FUNC)); } '. –
Если вам нужно скопировать лямбду, потому что это член класса, то вам нужно скопировать его, конец истории. Но в чем проблема - в лучшем случае ref-capture lambda будет содержать несколько ссылок, которые не так дорого копировать. –
Это то, на что были сделаны ссылки на C++ rvalue. –