12

The new auto keyword that we got in C++11 looks quite templat'ish to me so my question is - will it incur the same compile time bloat as templates do?

The same question in regards to polymorphic lambdas:

 [](auto val) {…}

this is essentially a template lambda - will this impact compile time or not?

Enlico
  • 23,259
  • 6
  • 48
  • 102
Zeks
  • 2,265
  • 20
  • 32

2 Answers2

18

The auto keyword of C++11 is far less heavyweight than templates - its compile-time "overhead" is comparable to that of sizeof, which means it's close to zero.

Unlike templates where the compiler needs to perform sizeable amount of computation during the expansion (the template language in C++ is Turing-complete), the auto keyword requires the compiler to figure out the type of an expression, which is something the compiler knows anyway. In fact, it would have to figure out the type of the expression even without the auto keyword to decide if type conversions need to be applied.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 12
    Polymorphic lambdas, as shown in the question, will actually generate `template operator()(_Unnamed val)`. – Xeo Jul 07 '13 at 00:32
  • @Xeo I do not know much about polymorphic lambdas yet - I guess I need to read up on them. I wish I could try it out, though my understanding is that there is no publicly available implementation yet. – Sergey Kalinichenko Jul 07 '13 at 03:04
  • 1
    The reference implementation is publicly available: http://faisalv.github.io/clang-glambda/ – Jonathan Wakely Jul 11 '13 at 22:52
12

What most people mean by "template bloat" is a myth. A template instantiated twice produces no more code than two separate functions that handle those same types. If you instantiate the template thousands of times you'll get lots of code, but if you write thousands of functions you'll get the same amount of code (see Diet Templates for some genuine ways carelessly defining templates can lead to some "bloat".) Templates can affect compilation time, but that is not "bloat".

The auto keyword is not a template, it uses the same rules of type deduction as templates, but if you write auto i = 1; there is only one "instantiation" i.e. the auto only has to deduce one type, and it produces exactly the same code as int i = 1; so there can't be any bloat. It's just alternative syntax for declaring a variable. Zero bloat.

Now polymorphic lambdas are different, they define a type with a member function template operator(), so each time you call the closure's operator() with different argument types you will instantiate another specialization of the function template, but that has nothing to do with auto, the use of auto is just syntax for declaring a template. If you call it thousands of times you'll get lots of code generated but no more than if you used thousands of different lambda expressions for the specific types you use (you almost certainly get less code with the generic lambda, because there's only one closure type so less RTTI and type names for the compiler to create and store in memory.)

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 1
    "A template instantiated twice produces no more code than two separate functions that handle those same types." Actually, I think that's _exactly_ the template bloat being referred to. In C it's common to force conversions to a set type, and then only have one body. templates _must_ have one body per type, even if the types are very similar (or even identical) – Mooing Duck Jul 11 '13 at 22:56
  • Also the effect on template compile time (according to my understanding) revolved around the fact that all templates must be implemented in the headers, causing headers to be large and complex and numerous, which has effects on compile time. Writing a thousand manual instantiations does _not_ have this issue, because then headers only have declarations, not definitions. – Mooing Duck Jul 11 '13 at 22:57
  • 1
    @MooingDuck, then you're comparing apples and oranges. If the functions were all `inline` it would be a fair comparison. Anyway, there _is_ a negative effect on compile-time for each new instantiation of a template, it's not just due to code in headers. Instantiating templates is expensive for the compiler. – Jonathan Wakely Jul 11 '13 at 22:59
  • Worth mentioning also that instantiating a template twice is much faster than compiling the equivalent two functions. – Potatoswatter Jul 11 '13 at 23:00
  • Yes, I am comparing apples to oranges. The problem is that C can do both apples _and_ oranges, and templates can _only_ do apples, which have negative side effects on compilation time. – Mooing Duck Jul 11 '13 at 23:00
  • I'm actually very pro-templates, I'm just arguing because I think your post is inaccurate. – Mooing Duck Jul 11 '13 at 23:01
  • 1
    @MooingDuck, What part's inaccurate? I don't even understand your first comment, if two instantiations of a function template produce 2N bytes of code and two functions produce N bytes each, where's the bloat? And anything C can do C++ can do too, see the Diet Templates slides for discussion of how to combine the two approaches. Are you saying "bloat" refers to compile time only? Because that is **not** what most people mean when they say "template bloat" – Jonathan Wakely Jul 11 '13 at 23:05
  • @JonathanWakely: It's true that anything C can do, C++ can do too, but compare code that instantiates `std::vector`, `std::vector`, `std::vector`, and `std::vector`, and then `std::sort`s them. Few C++ coders would think twice about it. But any C coder would simply write a `int_vector` and sort that, resulting in _significantly_ less code being produced. The vectors _could_ share code in theory, but I would be shocked if they did in practice. Instead, they bloat. (Slide 15 mentions this) – Mooing Duck Jul 11 '13 at 23:16
  • Actually, I just got to slide 22. I concede. Hadn't known about that optimization; – Mooing Duck Jul 11 '13 at 23:19
  • Unrelated, on slide 45, you have `tree_iterator`. I'm pretty sure an actual implementation would need to be more like `tree_iterator::pointer, typename Allocator::reference>`, and maybe other allocator bits in there. Point is valid though. – Mooing Duck Jul 11 '13 at 23:28
  • Only the `pointer` type actually, allocators' `reference` types are useless, but I was trying to avoid slide bloat ;-) See the SCARY paper for the real details – Jonathan Wakely Jul 11 '13 at 23:29
  • 1
    Anyway, basically you're arguing with me by making the same points I made in those slides three years ago ... I stand by my answer, what most people refer to as "template bloat" doesn't exist, but see the slides for some real causes of bloat. What's inaccurate? – Jonathan Wakely Jul 11 '13 at 23:34