Detail C++ function templates and separate compilation modes

  • 2020-11-18 06:22:57
  • OfStack

1. Separate compilation mode

A program (project) is implemented by several source files, and each source file is compiled separately to generate the target file. Finally, the process of connecting all the target files to form a single 1 executable file is called the split compilation mode.

2. Error while linking using function templates

In C++ programming, it is a very common practice to define a function in one source file and then use that function in another. However, if you define and call a function template this way, a compilation error will occur.

The following program consists of three files: func.h to declare the function template, func.cpp to define the function template, and main.cpp to contain the func.h header file and to call the corresponding function template.


/***func.h***/
template<class T> void func(const T&);
/***end func.h***/

/***func.cpp***/
#include <iostream>
using namespace std;

#include "func.h"
template<class T> void func(const T& t)
{
 cout<<t<<endl;
}
/***end func.cpp***/

/***main.cpp***/
#include <stdio.h>
#include "func.h"

int main()
{
 func(3);
}
/***end main.cpp***/

This is a very cleanly structured program, but it does not compile. The error message under VS2017 is:

[

Unparsable foreign symbol "void, ES28en func < int > (int const & )" (??$func@H@@YAXABH@Z)

]

The reason is the split compilation mode. In separate compilation mode, func.cpp generates a target file called func.obj, and since no function template call occurs in the func.cpp file, the function template is not used func<T> Instantiate as a template function func<int> In func.obj, the template function cannot be found func<int> Implementation code. In the source file main.cpp, although the function template is called, there is no template code to instantiate it. In other words, you can't find template functions in ES52en.obj func<int> Implementation code. In this way, it will appear when the link is made func<int> Undefined error.

3. Solutions

3.1 Put the definition of the function template in the header file

A simple solution is to template the function func<T> The definition is written in the header file func.h. In this way, as long as the header file is included, the function template code is included, and once the function call occurs, the function template code can be instantiated. Although simple and feasible, this method has the following disadvantages.
(1) The definition of the function template is written into the header file, exposing the implementation details of the function template.
(2) Does not comply with the rules for separating the compilation mode, because the separation of the compilation mode requires the function prototype declaration to be placed in the header file and the definition in the source file.

Note: In this way, if the same instantiated template template entity exists in multiple target files, the link does not report a function redefinition error, unlike normal functions, because the compiler optimizes the instantiated duplicate template function entity, leaving only one code entity. If you keep a copy of the function template entity in different source files, you will create code redundancy, and in fact, this is a solution to code redundancy.

3.2 Separate compilation mode is still adopted

Is there any way to find the corresponding template function code when the function template is instantiated? One possible solution is to use the keyword export. In other words, when defining the function template in ES74en.cpp, write the function template header as:


export template<class T> void func(const T& t);

The purpose is to tell the compiler that the function template may be instantiated in another source file. This is one of the least burdensome solutions for programmers, but almost all compilers today do not support the export keyword, including VC++ and GNU C++.

3.3 Show instantiation

Display instantiation is also called external instantiation. The instantiation of a function template when no function call occurs, or the instantiation of a class template when no class template is used is called template display instantiation.

The problem encountered above is that the template function is not found in ES89en.obj and ES91en.obj func<int> In func.cpp, the function template is set func<T> Displays instantiated template functions func<int> .


template void func<int>(const int&); // Function template displays instantiation 

In this way, you can generate template functions on func.cpp func<int> The instantiation code, after compilation will produce the function of the base 2 code, for other source file link, the program can run normally. When the implementation of the member function of the class template is defined in the source file, the error of function definition cannot be found when the member function is called through the object of the template class. The same method can be used to solve this problem, which will not be described further.

The above is a detailed explanation of C++ function template and split compilation mode, more information about C++ function template and split compilation mode, please pay attention to other related articles on this site!


Related articles: