Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested lambda expressions are very slow to compile and generate huge object file by Visual C++

I find that nested lambda expressions are very slow to compile and generate huge .obj files. For example, on my computer, the following code generates a obj file of size 4766 KB:

int main()
{
  auto f = []
  {
    auto f = []
    {
      auto f = []
      {
        auto f = []
        {
          auto f = []
          {
          };
        };
      };
    };
  };
}

And the following code (one more nesting level is added) will cause a C1128 error.

int main()
{
  auto f = []
  {
    auto f = []
    {
      auto f = []
      {
        auto f = []
        {
          auto f = []
          {
            auto f = []
            {
            };
          };
        };
      };
    };
  };
}

Also, they are very slow to compile. Is there any explanation for this? I'm using Visual C++ 2013.

Update

This seems to be a bug in Visual C++, I've reported it to Microsoft: https://connect.microsoft.com/VisualStudio/feedback/details/813755/nested-lambdas-in-visual-c-2013-are-very-slow-to-compile-and-generate-huge-object-file.

like image 714
EFanZh Avatar asked Jan 14 '14 13:01

EFanZh


People also ask

How to use lambda expressions in C++?

Example. Because lambda expressions are typed, you can use them with C++ templates. The following example shows the negate_all and print_all functions. The negate_all function applies the unary operator- to each element in the vector object. The print_all function prints each element in the vector object to the console.

What is nested lambda function?

When we use lambda function inside another lambda function then it is called Nested Lambda Function. Here, when the object o with parameter 4 is called, the control shift to f () which is caller object of the whole lambda function. Then the following execution takes place-

Why can’t the compiler cache a delegate created by a Lambda?

As you pass the local variable x to the lambda, the compiler is unable to cache a created delegate. Let’s look at the decompiled code: There it is. A new instance of the c__DisplayClass1 () is created each time the Substring method is called. The parameter x we pass to the lambda is implemented as a public field of c__DisplayClass1.

What is the difference between lambda expressions and linqs?

The concepts of LINQ queries and lambda expressions are closely connected and have very similar implementation ‘under the hood.’ This means that all concerns we discussed for lambdas are also true for LINQs. If your LINQ query contains a closure, the compiler won’t cache the corresponding delegate.


1 Answers

Not sure how useful such deeply nested lambdas are but for what it is worth as far as I can tell this is a bug, the Visual Studio compiler limits document states (emphasis mine):

The C++ standard recommends limits for various language constructs. The following is a list of constructs where the Visual C++ compiler does not implement the recommended limits. The first number is the recommended limit and the second number is the limit implemented by Visual C++:

and includes the following bullet:

Nesting levels of compound statements, iteration control structures, and selection control structures [256] (256).

If we look at the grammar in the C++ draft standard compound-statement will eventually get back to primary-expression which includes lambda-expression. So Visual Studio should support up to 256 levels of nesting.

You could also see this by looking at the grammar for lambda-expression which is as follows:

lambda-introducer lambda-declaratoroptcompound-statement

The draft standard has a set of recommend limits in Annex B but they are only guidelines and do not determine compliance.

Update

The bug report the OP filed was updated recently to indicate this will be fixed in a future release.

like image 79
Shafik Yaghmour Avatar answered Sep 28 '22 04:09

Shafik Yaghmour