Description: This article translated from section 6 of Chapter 6 of the Book of C Template: The Complete Guide. Recently, I saw a post on the template in the C forum. When I thought I had a template, I was also confused for similar problems, so I translated this article, I hope to help beginners.
Template code has several different organizations, this paper introduces the most popular way: including mode.
Link error
Most C / C programmers organize their non-template code to below:
· Class and other types are all placed in the header file, which have. HPP (or .h, .h, .hh, .hxx) extension.
• For global variables and (non-inline) functions, only the declaration is placed in the header file, and define in the point C file, these files have .cpp (or .c, .c, .cc, .cxx) extension .
This organization is working very well: it makes it easy to access the type definition required for programming and avoid errors from the "variable or function repetition definition" from the linker.
Due to the impact of the above organizational mode, the template programming novice often makes a same mistake. Below this short program reflects this error. Just like "normal code", we define templates in header files:
// Basics / MyFirst.hpp
#ifndef myfirst_hpp
#define myfirst_hpp
// Declaration of Template
Template
Void Print_TypeOf (T Const &);
#ENDIF // myfirst_hpp
Print_typeof () declares a simple accessory function to print some types of information. The definition of the function is placed in the point C file:
// Basics / MyFirst.cpp
#include
#include
#include "myfirst.hpp"
//Mplementation / definition of template
Template
Void Print_TypeOf (t const & x)
{
Std :: cout << TypeId (x) .name () << std :: end1
}
This example uses the TypeID operator to print a string, which describes the type information of the incoming parameter.
Finally, we use our templates in another point C file, in this file, template declaration is #include:
// Basics / MyFirstMain.cpp
#include "myfirst.hpp"
// use of the template
int main ()
{
Double ICE = 3.0;
Print_typeof (ip); // Call Function Template for Type Double
}
Most C compilers are likely to accept this program, without any issues, but the linker is probably reporting an error indicating that the definition of the lack of function print_typeof ().
The reason for this error is that the definition of the template function print_typeof () has not been added (instantiate). In order to develop a template, the compiler must know which definition should be turned, and what kind of template parameters are used. Unfortunately, in the previous example, the two groups of information exist in different files that are separately compiled. So, when our compiler sees calls to print_typeof (), but does not see this function is a Double type, it is only assumed that such definition is provided elsewhere, and creates one of the defined references ( The linker uses this reference parsing). On the other hand, when the compiler processes myfirst.cpp, this file does not have any indication that it must be defined for the special parameters it contains. Template in header file
Solving the general solution to this problem is that the same method is used with us using macro or inline functions: We use the template definition to enter the header file of the declaration template. For our example, we can achieve your go by adding #include "myfirst.cpp" to myfirst.hpp files, or contains myfirst.cpp files in each point C file using our templates. Of course, there is a third method that deletes myfirst.cpp files and overrides myfirst.hpp files so that it contains all template declarations and definitions:
// Basics / Myfirst2.hpp
#ifndef myfirst_hpp
#define myfirst_hpp
#include
#include
// Declaration of Template
Template
Void Print_TypeOf (T Const &);
//Mplementation / definition of template
Template
Void Print_TypeOf (t const & x)
{
Std :: cout << TypeId (x) .name () << std :: end1
}
#ENDIF // myfirst_hpp
This method of tissue template code is called the included mode. After such adjustments, you will find that our program has been able to compile, link, and execute it.
From this method we can get some observations. The most worthless point is that this method adds overhead that contains myfirst.hpp to a considerable extent. In this example, this overhead is not caused by a template defined itself, but is caused by such a fact that we must include the header file used in our template, in this example is
This is indeed a problem in practice because it adds the compiler to compile a actual program. We will therefore verify that other possible methods in future sections to solve this problem. But in any case, the program in the real world spends an hour to compile the link is fast (we have encountered a few days to compile from the source code).
Thinking of compile time does not talk, we strongly recommend that if you might try to configure the mode organization template code as possible.
Another observation is that the most important difference between the non-inline template function and the inline function and the macro is that it does not expand on the call. Instead, when the template function is activated, a new copy of this function will be generated. Since this is an automated process, the compiler may generate two identical copies in different files, causing the linker to report an error. In theory, we don't care about this: This is something that the compiler designer should care. In fact, most of the time everything is normal, we don't have to deal with this situation at all. However, this problem occasionally occasionally for large projects that need to create their own libraries. Finally, it is necessary to point out that in our example, the method applied to the normal template function is also suitable for member functions of the template class and static data members, and template member functions.