1

What is the difference in the resulting binary, when we compare this code:

struct S {
    template<typename... Args>
    void operator()(Args... args) { /* ... */ }
};

// And then inside some block:
S s;
s(42);
s(3.14, "Hi!");
s("Hi!", 3.14);

...to this code:

const auto l = [](auto... args) { /* ... */ };

// And then inside some block:
l(42);
l(3.14, "Hi!");
l("Hi!", 3.14);

As far as I understand, the struct code creates 3 template instantiations for operator(), all of which appear as symbols in the binary. What about the lambda? The compiler creates an object similar to s. But if it's an unnamed class type, does it create symbols in the binary?

Motivation: I've used a template-heavy library where I had to enable /bigobj. I would like to avoid that and I'm wondering if lambdas can help against template code bloat. Is this defined in the standard, or dependent on compiler implementation?

max66
  • 65,235
  • 10
  • 71
  • 111
basteln
  • 2,483
  • 2
  • 19
  • 20
  • Inlining would actually help in this case, removing the symbols for the lambdas. – Guillaume Racicot Sep 12 '18 at 23:26
  • Try putting the struct in an unnamed namespace. – Kerrek SB Sep 12 '18 at 23:33
  • 1
    Look at your compiler output and find your *actual problem*. Templates, etc. are syntactic sugar. "Code bloat" is not nearly as relevant now as it was 20 years ago, and storage costs far less than developer time. What is your actual goal here? Your examples do exactly the same thing. IF it compiles, it's because the compiler will generate different versions for `auto` as it does for templates. `auto` does not provide *dynamic typing*. It's still a statically-typed language, and you need different versions for different types. Templates, other compiler magic - doesn't matter. – 3Dave Sep 12 '18 at 23:34
  • I would assume the latter example doesn't even compile because the arguments have different types in the different invocations? – crazypeter Sep 12 '18 at 23:46
  • @crazypeter That's a feature of generic lambdas. – François Andrieux Sep 13 '18 at 00:14
  • @3Dave As I wrote, my "actual goal" is to avoid /bigobj. Can you give me a reference to prove that the compiler output (except maybe symbol names) is exactly the same in the two examples? My question is: Since a lambda creates an unnamed class type, does it create symbols in the binary? – basteln Sep 13 '18 at 07:16

1 Answers1

1

I think, unfortunately, lambda can't help you solve the problem of code bloat. For your example, like struct S, The compiler will also create three different operator () for lambda.

In order to prove my point of view, I compiled the following program with g++ 8.1.0 on Linux.

int main()
{
    const auto l = [](auto... args) { /* ... */ };
    l(42);
    l(3.14, "Hi!");
    l("Hi!", 3.14);
}

and then use the nm command to view the binary file, the result is as follows:

output of nm command

It is not difficult to see that the last three lines are the symbols of the three operator (). So, in this case, lambda and struct S are not fundamentally different.

eprom
  • 226
  • 2
  • 11