复制 - 分配相同类型的C ++ lambda

时间:2017-08-15 15:46:29

标签: c++ lambda c++14

C ++ lambda具有已删除的复制赋值运算符。我不知道为什么。然而,这种限制可以很容易地解决。但我感觉不太好。以下方法可能有什么问题? Live code

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 
}

我可以想到两个原因:

  1. 施工可能会抛出,而dest主要部分仍然未初始化,并在主要部分再次被销毁。双删除。
  2. 如果一个写得不好的库抛出析构函数,析构函数可能会抛出。
  3. 施工期间的例外情况也可以通过强有力的异常安全保障来解决。考虑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();
    }
    

1 个答案:

答案 0 :(得分:1)

您无需(复制/移动)分配lambda。

class lambda {
    std::shared_ptr<int> v;
public:
    explicit lambda(int i) : v(make_shared(i)) {}
    void operator()() { std::cout << *v << "\n"; }
}

auto make_lambda(int i) {   
    return lambda(i);
}

或者,对于记忆案例,您不要更改memoise

template <typename Func>
auto memoized_recursion(Func func, Cache c = Cache::NO_RECLAIM)
{
  static std::unordered_map<Func, decltype(memoise(func))> functor_map;

  if(Cache::RECLAIM == c)
    return functor_map.insert_or_assign(func, memoize(func)).first->second;
  else
    return functor_map.insert(func, memoize(func)).first->second;
}