C++ – Understanding how Lambda closure type has deleted default constructor

cconstructordefaultlambda

From 5.1.2

[19] The closure type associated with a lambda-expression has a deleted (8.4.3) default constructor and a deleted
copy assignment operator. It has an implicitly-declared copy constructor (12.8) and may have an implicitlydeclared
move constructor (12.8). [ Note: The copy/move constructor is implicitly defined in the same way
as any other implicitly declared copy/move constructor would be implicitly defined. —end note ]

I'm reading through C++ Primer 14.8.1 which explains lambda expressions being translated by the compiler in to an unnamed object of an unnamed class. How is it I can I define objects of lambda functions which do not contain a lambda capture, if the default constructor is deleted?

 auto g = [](){};

Is this not conceptually the same as…

 class lambdaClass{
 public:
      lambdaClass() = delete;
      lambdaClass& operator=(const lambdaClass&) = delete;
      void operator()(){ }

      //copy/move constructor and destructor implicitly defined
};

auto g = lambdaClass(); //would be an error since default is deleted.

If there was a capture then a constructor other than the default constructor would be defined and it would be okay to initialise objects of such (as long as a parameter was passed). But if there is no capture and the default constructor is deleted, it doesn't seem consistent conceptually that a lambda class object can be created.

Edit: Hmm, maybe the conception that the lambda class creates constructors depending on its lambda captures is unfounded despite this being how it's described in C++ Primer (I can find no quote of it in the standard), because the following code does not work even though I would expect it to conceptually:

int sz = 2;
auto a = [sz](){ return sz;};
decltype(a) b(10); //compiler error
decltype(a) b = a; //all good though

Best Answer

The relationship between a closure to lambda is similar to object to class.

The C++11 standard says that the closure! type has no default constructor, and that is correct because it doesn't say it has no constructor.

The lambda is used to create a closure. But your quoted parapgraph will change for C++14.

ClosureType() = delete;                     // (until C++14)
ClosureType(const ClosureType& ) = default; // (since C++14)
ClosureType(ClosureType&& ) = default;      // (since C++14)

Closure types are not DefaultConstructible. Closure types have a deleted (until C++14) no (since C++14) default constructor. The copy constructor and the move constructor are implicitly-declared (until C++14) declared as defaulted (since C++14) and may be implicitly-defined according to the usual rules for copy constructors and move constructors.

http://en.cppreference.com/w/cpp/language/lambda