Skip to content

Commit 1d2f063

Browse files
author
Paul Dempsey
authored
cpp for c++ code samples, edits
- Use cpp for c++ code examples so they get syntax highlighting - Edit for correct standard MS notation for `code literal`, **keyword**. - Make headings parallel and aligned with the defined terms wrt the inclusion/explicit instantiation models
1 parent 8abe610 commit 1d2f063

File tree

1 file changed

+16
-13
lines changed

1 file changed

+16
-13
lines changed

docs/cpp/source-code-organization-cpp-templates.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ caps.latest.revision: 5
1515
manager: "ghogen"
1616
---
1717
# Source code organization (C++ Templates)
18-
When defining a class template, you must organize the source code in such a way that the member definitions are visible to the compiler when it needs them. You have the choice of using the *inclusion model* or the *explicit instantiation* model. In the inclusion model, you include the member definitions in every file that uses a template. This approach is simplest and provides maximum flexibility in terms of what concrete types can be used with your template. Its disadvantage is that it can increase compilation times. The impact can be significant if a project and/or the included files themselves are large. With the explicit instantiation approach, the template itself instantiates concrete classes or class members for specific types. This approach can speed up compilation times, but it limits usage to only those classes that the template implementer has enabled ahead of time. In general, we recommend that you use the inclusion model unless the compilation times become a problem.
19-
20-
## Background
21-
Templates are not like ordinary classes in the sense that the compiler does not generate object code for a template or any of its members. There is nothing to generate until the template is instantiated with concrete types. When the compiler encounters a template instantiation such as `MyClass<int> mc;`, and no class with that signature exists yet, then it generates a new class. It also attempts to generate code for any member functions that are used. If those definitions are in a file that is not #included, directly or indirectly, in the .cpp file that is being compiled, the compiler can't see them. From the compiler's point of view, this isn't necessarily an error because the functions may be defined in another translation unit, in which case the linker will find them. If the linker does not find that code, it raises an **unresolved external** error.
22-
23-
## The inclusion model
18+
19+
When defining a class template, you must organize the source code in such a way that the member definitions are visible to the compiler when it needs them. You have the choice of using the *inclusion model* or the *explicit instantiation* model. In the inclusion model, you include the member definitions in every file that uses a template. This approach is simplest and provides maximum flexibility in terms of what concrete types can be used with your template. Its disadvantage is that it can increase compilation times. The impact can be significant if a project and/or the included files themselves are large. With the explicit instantiation approach, the template itself instantiates concrete classes or class members for specific types. This approach can speed up compilation times, but it limits usage to only those classes that the template implementer has enabled ahead of time. In general, we recommend that you use the inclusion model unless the compilation times become a problem.
20+
21+
## Background
22+
23+
Templates are not like ordinary classes in the sense that the compiler does not generate object code for a template or any of its members. There is nothing to generate until the template is instantiated with concrete types. When the compiler encounters a template instantiation such as `MyClass<int> mc;` and no class with that signature exists yet, it generates a new class. It also attempts to generate code for any member functions that are used. If those definitions are in a file that is not #included, directly or indirectly, in the .cpp file that is being compiled, the compiler can't see them. From the compiler's point of view, this isn't necessarily an error because the functions may be defined in another translation unit, in which case the linker will find them. If the linker does not find that code, it raises an **unresolved external** error.
24+
25+
## The inclusion model
26+
2427
The simplest and most common way to make template definitions visible throughout a translation unit, is to put the definitions in the header file itself. Any .cpp file that uses the template simply has to #include the header. This is the approach used in the Standard Library.
2528

26-
```
29+
```cpp
2730
#ifndef MYARRAY
2831
#define MYARRAY
2932
#include <iostream>
@@ -49,21 +52,21 @@ public:
4952
}
5053
};
5154
#endif
52-
5355
```
5456

5557
With this approach, the compiler has access to the complete template definition and can instantiate templates on-demand for any type. It is simple and relatively easy to maintain. However, the inclusion model does have a cost in terms of compilation times. This cost can be significant in large programs, especially if the template header itself #includes other headers. Every .cpp file that #includes the header will get its own copy of the function templates and all the definitions. The linker will generally be able to sort things out so that you do not end up with multiple definitions for a function, but it takes time to do this work. In smaller programs that extra compilation time is probably not significant.
5658

57-
## Explicit instantiation
59+
## The explicit instantiation model
60+
5861
If the inclusion model is not viable for your project, and you know definitively the set of types that will be used to instantiate a template, then you can separate out the template code into an .h and .cpp file, and in the .cpp file explicitly instantiate the templates. This will cause object code to be generated that the compiler will see when it encounters user instantiations.
5962

6063
You create an explicit instantiation by using the keyword template followed by the signature of the entity you want to instantiate. This can be a type or a member. If you explicitly instantiate a type, all members are instantiated.
6164

62-
```
65+
```cpp
6366
template MyArray<double, 5>;
6467
```
6568

66-
```
69+
```cpp
6770
//MyArray.h
6871
#ifndef MYARRAY
6972
#define MYARRAY
@@ -102,7 +105,7 @@ void MyArray<T,N>::Print()
102105
template MyArray<double, 5>;template MyArray<string, 5>;
103106
```
104107

105-
In the previous example, the explicit instantiations are at the bottom of the .cpp file. A MyArray may be used only for `double` or `string` types.
108+
In the previous example, the explicit instantiations are at the bottom of the .cpp file. A `MyArray` may be used only for **double** or **string** types.
106109

107110
> [!NOTE]
108-
> In C++11 the `export` keyword was deprecated in the context of template definitions. In practical terms this has little impact because most compilers never supported it.
111+
> In C++11 the **export** keyword was deprecated in the context of template definitions. In practical terms this has little impact because most compilers never supported it.

0 commit comments

Comments
 (0)