Возьмите этот придуманный код, где нам нужно создать лямбду в конструкторе, который захватывает this
в подвижном типе:
#include <functional>
#include <string>
#include <iostream>
using namespace std::string_literals;
namespace
{
class foo
{
public:
template <typename T>
explicit foo(std::string key, T val) :
key_{std::move(key)}
{
f_ = [this, v = std::move(val)]() {
std::cout << key_ << ": " << v << std::endl;
};
}
void print()
{
f_();
}
private:
std::function<void ()> f_;
std::string key_;
};
}
int main()
{
auto f1 = foo("hello", "goodbye"s);
auto f2 = std::move(f1);
f2.print();
return EXIT_SUCCESS;
}
В этом примере мы используем лямбду для стирания типа, но это действительно не имеет значения - все, что важно, это то, что мы фиксируем this
в лямбду в конструкторе.
Запуск этого даст:
: goodbye
Это (я думаю) потому, что печатаемый элемент key_
является пустой оболочкой перемещенного из f1::key_
, то есть захваченный указатель this
все еще указывает на f1
, несмотря на то, что теперь находится внутри f2
.
Я могу придумать несколько (неуклюжих) способов обойти это, которые зависят от обстоятельств, но есть ли стандарт / общий / лучше / и т.д. способ эффективного обращения к экземпляру-владельцу изнутри лямбды?