30

I'm reading a book about how templates work, and I'm having difficulty understanding this explanation of templates.

It says

When the compiler sees the definition of a template, it does not generate code. It generates code only when we instantiate a specific instance of the template. The fact that code is generated only when we use a template (and not when we define it) affects how we organize our source code and when errors are detected...To generate an instantiation, the compiler needs to have the code that defines a function template or class template member function. As a result, unlike non-template code, headers for templates typically include definitions as well as declarations.

What exactly does it mean by "generate code"? I don't understand what is different when you compile function templates or class templates compared to regular functions or classes.

cigien
  • 57,834
  • 11
  • 73
  • 112
FrostyStraw
  • 1,628
  • 3
  • 25
  • 34

7 Answers7

31

The compiler generates the code for the specific types given in the template class instantiation.

If you have for instance a template class declaration as

template<typename T>
class Foo
{
public:
     T& bar()
     {
         return subject; 
     }
private:
     T subject;
};

as soon you have for example the following instantiations

Foo<int> fooInt;
Foo<double> fooDouble;

these will effectively generate the same linkable code as you would have defined classes like

class FooInt
{
public:
     int& bar()
     {
         return subject; 
     }
private:
     int subject;
}

and

class FooDouble
{
public:
     double& bar()
     {
         return subject; 
     }
private:
     double subject;
}

and instantiate the variables like

FooInt fooInt;
FooDouble fooDouble;

Regarding the point that template definitions (don't confuse with declarations regardless of templates) need to be seen with the header (included) files, it's pretty clear why:
The compiler can't generate this code without seeing the definition. It can refer to a matching instantiation that appeared first at linking stage though.

What does a non-template member function have that allows for it to be defined outside of the header that a template function doesn't have?

The declaration of a non-template class/member/function gives a predefined entry point for the linker. The definition can be drawn from a single implementation seen in a compiled object file (== .cpp == compilation unit).
In contrast the declaration of a templated class/member/function might be instantiated from arbitrary compilation units given the same or varying template parameters. The definition for these template parameters need's to be seen at least once. It can be either generic or specialized.

Note that you can specialize template implementations for particular types anyway (included with the header or at a specific compilation unit). If you would provide a specialization for your template class in one of your compilation units, and don't use your template class with types other than specialized, that also should suffice for linking it all together.

I hope this sample helps clarifying what's the difference and efforts done from the compiler.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Ahh...so it's kinda of like...when using templates, the compiler sort of "writes the function" for the specific type so that I don't have to do it myself..and that's what it means by generate? Although I kinda don't get why this means that the declarations of the functions should be included in the header files – – FrostyStraw Nov 05 '13 at 20:38
  • ...ahh, I don't know what I'm not seeing but I still just don't get it. What does a non-template member function have that allows for it to be defined outside of the header that a template function doesn't have? @g-makulik – FrostyStraw Nov 05 '13 at 21:10
  • I know it's been a few days but for some reason I just really really do not understand your explanation. It seems that a really good understanding of how the compiler works is needed for it, or I just don't know why it's not sinking in. Thanks for trying though, hopefully someday all of this makes sense lol @g-makulik – FrostyStraw Nov 08 '13 at 01:51
  • I assume the compiler is smart enough to generate code only once per mentioned instance? e.g. if I mention Foo in FileA.cpp and FileB.cpp, it will only generate the code once, correct? – vexe May 26 '17 at 06:10
  • @vexe Sure. Your assumption is correct.Was my answer somehow unclear about that? – πάντα ῥεῖ May 26 '17 at 06:12
  • @πάντα ῥεῖ I don't see how that could be the case, since FileA.cpp and FileB.cpp are compiled as separate compilation units? What if I would use Foo in both files, but (being determined to break things) I include a different definition of template class Foo in both compilation units. Would the compiler be able to detect this? Would the linker? – PieterNuyts Aug 24 '17 at 07:30
  • Why the compiler generates the definition instead of a declaration. – BAKE ZQ Sep 02 '20 at 03:52
  • @BAKEZQ I suppose you know the difference of definition and declaration in C++? In fact the compiler generates both from the template. Otherwise I don't understand your question? – πάντα ῥεῖ Sep 02 '20 at 14:19
  • @πάνταῥεῖ Why the compiler generates both from the templated. – BAKE ZQ Sep 02 '20 at 15:26
  • @BAKEZQ I don't understand your quesiton. What else would you expect? – πάντα ῥεῖ Sep 02 '20 at 15:28
  • I expect the compiler does like I manually wrote a declaration. – BAKE ZQ Sep 02 '20 at 15:30
  • @BAKEZQ It does so, and for the definition as well. I said everything relevant in my answer already. I'd recommend you read it thoroughly again (including the links). – πάντα ῥεῖ Sep 02 '20 at 15:32
  • If the compiler wrote an empty definition, how can the link error be produced? – BAKE ZQ Sep 02 '20 at 15:34
  • @BAKEZQ Did you see this: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file ? – πάντα ῥεῖ Sep 02 '20 at 15:35
  • Yes, but that doesn't solve my confusion. And all answers related to this question/link doesn't make sense to me. The second solution works is somewhat a representation of the fact that only the declaration is generated when it's converted to an obj file, and the linker finds the definition in the second file. If this explanation true? – BAKE ZQ Sep 02 '20 at 15:48
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/220873/discussion-between---and-bake-zq). – πάντα ῥεῖ Sep 02 '20 at 15:50
  • Though the linker complains of not finding the reference, I found the obj file can be successfully generated by using g++ -E/-S/-c xxx – BAKE ZQ Sep 02 '20 at 15:50
23

A template is a pattern for creating code. When the compiler sees the definition of a template it makes notes about that pattern. When it sees a use of that template it digs out its notes, figures out how to apply the pattern at the point where it's being used, and generates code according to the pattern.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
5

What is the compiler suppose to do when it sees a template? Generate all the machine code for all possible data types - ints, doubles, float, strings, ... Could take a lot of time. Or just be a little lazy and generate the machine code for what it requires.

I guess the latter option is the better solution and gets the job done.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • 1
    I think I understand that part a little more now, but I still don't really get why that means that template declarations must be in the header files @Ed Heal – FrostyStraw Nov 05 '13 at 20:45
  • The .cpp file needs to know about them. Also the compiler needs to be able to generate the necessary machine code when it comes across the use of them for the appropriate type. – Ed Heal Nov 05 '13 at 20:49
3

The main point here is that compiler does not treat a template definition until it meets a certain instance of the template. (Then it can proceed, I guess, like it have a usual class, which is a specific case of the template class, with fixed template parameters.)

The direct answer to your question is: Compiler generates machine code from users c++ code, I think this is wat is meant here by word "generate code".

The template declaration must be in header file because when compiler compiles some source, which use template it HAVE only header file (included in source with #include macro), but it NEED whole template definition. So logical conclusion is that template definition must be in header.

klm123
  • 12,105
  • 14
  • 57
  • 95
1

When you create a function and compile it, the compiler generates code for it. Many compilers will not generate code for static functions that are not used.

If you create a templated function and nothing uses the template (such as std::sort), the code for the function will not be generated.

Remember, templates are like stencils. The templates tell how to generate a class or function using the given template parameters. If the stencil is not used, nothing is generated.

Consider also that the compiler doesn't know how to implement or use the template until it sees all the template parameters resolved.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

It won't straight away generate code. Only generates the class or template code when it comes across an instantiation of that template. That is, if you are actually creating an object of that template definition.

In essence, templates allow you abstract away from types. If you need two instantiations of the template class for example for an int and a double the compiler will literally create two of these classes for you when you need them. That is what makes templates so powerful.

cigien
  • 57,834
  • 11
  • 73
  • 112
Montaldo
  • 863
  • 8
  • 16
-1

Your C++ is read by the compiler and turned into assembly code, before being turned in machine code.

Templates are designed to allow generic programming. If your code doesn't use your template at all, the compiler won't generate the assembly code associated. The more data types you associate your template with in your program, the more assembly code it will generate.

Matt Harrison
  • 13,381
  • 6
  • 48
  • 66