0

I am confused by why a capturing lambda is not move assignable, but its manual definition (as struct with operator()) is.

Consider the following simplified code:

struct Environment {
  Environment(std::unique_ptr<int>&& p): ptr(std::move(p)) {}
  
  std::unique_ptr<int> ptr;
};

class LambdaCPPInsights
{
  public: 
  inline /*constexpr */ void operator()() const
  {
  }

  private: 
  std::shared_ptr<Environment> env;
  public: 
  LambdaCPPInsights(const std::shared_ptr<Environment> & _env)
    : env{_env}
  {}

};

constexpr const char* btos(bool b)
{
   return b ? "true" : "false";
}

int main()
{
  
  auto env =  std::make_shared<Environment>(std::make_unique<int>(4));
  
   std::cout << "True   lambda is move-assignable: " << btos(std::is_move_assignable_v< decltype([env = env]() {}) >) << std::endl;
   std::cout << "Manual lambda is move-assignable: " << btos(std::is_move_assignable_v< LambdaCPPInsights >);  

  return 0;
}

The class LambdaCPPInsights is the translated (and then renamed) lambda struct as given by cpp insights, should therefore be the same thing as the lambda defined by [env = env]() {}. However, the output of the previous code under gcc 11.2 and c++20 is:

True   lambda is move-assignable: false
Manual lambda is move-assignable: true

The example on godbolt is found here: https://godbolt.org/z/Yx3n9eGj5

What am I missing?

1 Answer 1

2

A lambda with a capture has a deleted copy assignment operator, which also implies that it has no implicit move assignment operator. See [expr.prim.lambda.closure]/13.

Your LambdaCPPInsights is not correctly reproducing the closure type. It should explicitly default the copy and move constructors, and explicitly delete the copy assignment operator.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.