C++ lambda表达式具有删除的复制分配操作符。我不知道为什么。但是,这个限制可以很容易解决。但我感觉不太好。以下方法会出现什么问题? Live code。复制分配相同类型的C++ lambda表达式
template <class T> void assign(T& dest, T&& val) {
dest.~T();
new (&dest) T(std::forward<T>(val));
}
auto make_lambda(int i) {
return [v=std::make_shared<int>(i)] {std::cout << *v << "\n"; };
}
int main() {
auto one = make_lambda(1);
assign(one, make_lambda(2));
one(); // prints 2
}
有可能是两个原因,我能想到的:
- 建设可能会引发和
dest
主主仍然未初始化和销毁稍后。双删除。 - 如果某个写得不好的库在析构函数中抛出,析构函数可能会抛出。
施工中的例外情况也可以通过强有力的例外安全保证来解决。考虑assignv2
:
template <class T>
void assignv2(T& dest, const T& src)
{
static std::allocator<T> alloc;
static typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
std::memcpy(&storage, &dest, sizeof(T));
try {
new (&dest) T(src);
}
catch(...) {
std::memcpy(&dest, &storage, sizeof(T));
throw;
}
reinterpret_cast<T*>(&storage)->~T();
}
这气味非常UB的。另外:为什么这样做?您可以*写一个具有所需复制语义的类,并在其中放入一个'operator()'。 – Caleth
这个舞蹈的动机是函数的自动记忆。 – Sumant
为什么你需要存储lambda来记忆函数?您只需要存储函数结果。 – rustyx