使用此人为设计的代码,我们需要在构造器中创建一个lambda,以捕获可移动类型的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;
}
在此示例中,我们使用lambda进行类型擦除,但这并不重要-重要的是我们在构造函数的lambda中捕获了this
。
Running this将产生:
: goodbye
(我认为)这是因为正在打印的key_
成员是移出的f1::key_
的空外壳,即捕获的this
指针仍指向{{1} },尽管现在位于f1
之内。
我可以想到几种针对具体情况的(笨拙的)方式,但是有标准/通用/更好/等等。 lambda内部有效引用拥有实例的方法?
答案 0 :(得分:1)
一个简单的解决方案可能是避免捕获this
并将其作为参数提供给函数对象。这样,您就可以自由地复制和移动功能对象,而不必考虑哪个实例拥有哪个功能对象。当需要调用该函数时,当前所有者可以将自身传递给该函数。
例如,这是您原始示例的外观:
#include <iostream>
#include <functional>
#include <string>
class foo
{
public:
template <typename T>
explicit foo(std::string key, T val) :
key_{ std::move(key) }
{
f_ = [v = std::move(val)](foo * const this_ptr) {
std::cout << this_ptr->key_ << ": " << v << std::endl;
};
}
void print()
{
f_(this);
}
private:
std::function<void(foo *)> f_;
std::string key_;
};