Incorrect multi-Definition of symbols in special template Functions

Source: Internet
Author: User

I am using a template-based library source code, which contains some template function features for specific types. Class templates, function templates, and template function features are all included in the header file. I am in my. cpp File
# Include the header file and compile the link project. However, to use this library throughout the project, I include the header file in stdafx. h.
. How can I organize header files to avoid multiple symbol definition errors? I use/Force: multiple, but I want to use a better solution.

Lee Kyung Jun


Actually, a better solution is used. I will explain it later, but first let me review how template function specialization works. Suppose you have a comparison between two operator-based and
Operator = Object template function:

template <typename T>
int compare(T t1, T t2)
{
return t1==t2 ? 0 : t1 > t2 ? 1 : -1;
}

The template returns zero or +/-1 based on whether a parameter is equal to, greater than, or less than the second parameter. It is a typical sorting function used for sorting sets. It is assumed that type T has
Operator = and operator> operations, and supports int, float, double, or DWORD
Type. However, it cannot be applied to a relatively conceited string (char * pointer), because this function compares the string pointer rather than the string itself:

LPCTSTR s1,s2;
...
int cmp = compare(s1,s2); // s1<s2? Oops!

To compare strings, you need a special Template Using strcmp or its tchar version _ tcscmp:

// specialization for strings
template<>
int compare<LPCTSTR>(LPCTSTR s1, LPCTSTR s2)
{
return _tcscmp(s1, s2);
}

That's right. The question now is: where to put this special feature? It is obviously placed in the header file of the template. But this will lead to multiple definition errors of symbols, just like Lee
In that case. The reason is obvious: Template specialization is a function, not a template. It is the same as the following statement:

int compare(LPCTSTR s1, LPCTSTR s2)
{
return _tcscmp(s1, s2);
}

There is no reason not to define the function in the header file -- but once this is done, you will not be able to # include
This header file. At least, there must be a link error. What should we do?
If you have mastered the template function specialization, that is, the function, rather than the template concept, you will realize that there are three options, exactly the same as normal functions; the features are converted to inline, extern, or
Static. For example, as shown below:

template<>
inline int compare<LPCTSTR>(LPCTSTR s1, LPCTSTR s2)
{
return _tcscmp(s1, s2);
}

This is the easiest and most common solution for most template libraries. Because the compiler directly extends inline functions without generating external symbols, # include
They have no problems. The linker does not have errors because there are no symbols with multiple definitions. For small functions like compare, inline
Everything you want is faster ).
However, if you have a long specialization, or for some reason, you don't want to make it inline, what should you do? In this case, it can be made into extern. The syntax is the same as that of a regular function:

// in .h header file
template<>
extern int compare<LPCTSTR>(LPCTSTR s1, LPCTSTR s2);

Of course, you have to implement compare somewhere. Some details are as follows:
See Figure 7. I am in a separate module Templ. cpp
It is connected to the main project. Templ. H is # include in stdafx. H, and stdafx. H is # include in
In the Templ. cpp and master module files, there is no link error in the generated project. Download the source code and try it yourself.
If you are writing a template library for another developer
The method will be uncomfortable, because you must create a link library (LIB) with the target module, which contains special features. If you already have
. Lib, there is nothing; if not, you may try to avoid introducing such a library. It is better to use only the header file to implement the template (less trouble ). The easiest way is to use
Inline, In addition, you can also put your special content in a separate header file to separate it from its declaration and require other developers to only include in one module #
Special. Another optional method is to put everything in a file and use preprocessing symbols to control instantiation:

#ifdef MYLIB_IMPLEMENT_FUNCS
template<>
int compare<LPCTSTR>(LPCTSTR s1, LPCTSTR s2)
{
return _tcscmp(s1, s2);
}
#endif

With this method, all modules contain this header file, but before including it, there is only one # define mylib_implement_funcs. This method does not support precompiled headers because the compiler uses
Any mylib_implement_funcs value in stdafx. h loads the pre-compiled version.
At the end of avoiding multiple definition errors of symbols, it is also the least used method to convert the code into static:

template<>
static int compare<LPCTSTR>(LPCTSTR s1, LPCTSTR s2)
{
return _tcscmp(s1, s2);
}

In this way, the linker will not go wrong, because static functions do not output their functions to the outside world, and they allow you to keep everything in a header file without introducing preprocessing symbols. However, it lacks efficiency because each module has a function copy. If the function is small enough, why not inline?
So Simply put: Make it "inline" or "extern. Generally
Inline. You must edit the header file in either of the two methods. If a third-party library does not have a header file, you must use the link option/Force: multiple.
There is no choice. When you are waiting to generate your project, you can tell the guy who is writing the library file-Why define the function template as inline or
Extern. That's what I said.

------------

The C ++ template concept typename name clearly indicates that the latter name is the type name, but the keyword typename is recently added to the Standard C ++ (16) how does the compiler analyze the template definition? (compile time analysis template definition (Note: It is not template instantiation ))
For the compiler, it does not always differentiate which expressions in the template definition are of type.

To enable the compiler to analyze the template definition, users must instruct the Compiler which expressions are type expressions,
The mechanism that tells the compiler that an expression is a type expression is to add the keyword typename before the expression.



(17) template type parameters:

It consists of a class or typename keyword followed by an identifier. In the template parameter table of the function.

These two keywords have the same meaning. They indicate that the parameter names after the template represent a potential built-in or user-defined type. The template parameter names are selected by the programmer.

The template type parameter can be used as a type indicator for the rest of the template definition.

1. The template type parameter name can be used to specify the return bits of the function template. (The return type of the function)
2. The template parameter name can only be used once in the same template parameter table, but the template parameter name can be reused between multiple function template declarations or definitions.
3. There is no limit on the number of times template parameters can appear in the function parameter table.
4. The template parameter names used by one template definition and multiple declarations do not need to be the same
5. If a function template has more than one template type parameter, the class or typename keyword must be prefixed before each template type parameter.
6. Multiple function arguments can be involved in the deduction process of real parameters in the same template. If the template parameters appear multiple times in the function parameter table, each derived type must match the first type derived from the template parameters.
These possible type conversion restrictions only apply to the function arguments that participate in the real-argument deduction process of the template. All type conversions of all other real parameters are allowed.
7.

(18) Non-type parameters of the template:
It is composed of a common parameter declaration. A non-type parameter in the template indicates that the parameter name represents
Potential value, which represents a constant in the template definition.

The module is not a type parameter
A constant value can appear in the rest of the template definition. It can be used where a constant is required, perhaps in
Specify the array size in the array declaration or use it as the initial value of the enumerated constant.

(19) template definition:
The keyword template is always placed at the beginning of the template definition and Declaration. The keyword is followed by a template separated by commas.
The parameter table template parameter list is enclosed by Angle brackets <> A smaller sign and a greater sign.
The list is a template parameter table that cannot be blank. The template parameter can be a template type parameter template type.
Parameter indicates a type, or a non-type parameter template nontype parameter.
It represents a constant expression. The function definition or declaration follows the template parameter table.

(20) template instantiation:
The replacement process of type and value is called template instantiation.

The function template specifies how to construct an independent function based on a group or more actual types or values.
Template instantiation

This process occurs implicitly. It can be seen as a side effect of calling a function template or taking the address of a function template. (21) template parameter table:
Template parameter list, a comma-separated template parameter table, is enclosed by Angle brackets <> A smaller sign and a greater sign.
The list is a template parameter table that cannot be blank. The template parameter can be a template type parameter template type.
Parameter indicates a type, or a non-type parameter template nontype parameter.
It represents a constant expression. (22) function parameter table :( 23) Real parameter deduction in the template :( can the return value type of the function be deduced ?)

The process of determining the type and value of template real parameters by using the type of function real parameters is called template real parameter deduction template argument deduction.

We can also explicitly specify the real parameters of the template instead of relying on the real parameter deduction process of the template.

When getting the address of a function template instance, you must be able to use the Context Environment to determine a unique type or value for a template real parameter,
If this unique type or value cannot be determined, a compilation time error occurs. when a function template is called, the check of the real parameter type determines the real parameter type and value of the template. this process is
Called template real parameter deduction template argument deduction

* *** The compiler does not consider the return type of the function template instance when determining the type of the template's real parameters during the real parameter deduction of the template.

To successfully deduct the real parameters of a template, you do not have to strictly match the type of the corresponding function parameter.
The following three types of conversions are allowed:
1. Left value conversion:

2. Limited conversion:

3. To a base class, the base class is converted to a class template:
(24) explicitly specify the template parameters

In some cases, the compiler may not be able to push the classes of the real parameters of the template.

In this case, we need to change the real parameter deduction mechanism of the template and explicitly specify the explicit specify
Template real parameters. The template real parameters are explicitly specified in the comma-separated list with Angle brackets <> A smaller than sign and
The signature is immediately followed by the name of the function template instance. However, when the real parameters of the template are explicitly specified, it is unnecessary to deduct the real parameters of the template.

We must note that the explicit template parameters should be used only when they are fully needed to solve the ambiguity or when the template parameters
When a template instance is used in a context that cannot be deduced, the compiler must first determine the type and value of the template's real parameters.
Second, if we modify the declaration in the program to change the type of the function arguments in the instance call of the function template, the compiler will automatically instantiate the function template with different templates. on the other hand, if explicit template parameters are specified, you must check whether the new type of explicit template parameters for function arguments is
No, it is still appropriate. Therefore, it is recommended that you save the real parameters of a slightly-formatted template when possible.

(25) returned values in the template

(26) Explicit template real parameter C ++ primer 3E (important)

(27) C ++ template compilation mode template compilation Model

(28) The "template parameter derivation mechanism" of the function is only a parameter, and the type of Return Value of the function cannot be deduced.

(29) function template explicit special C ++ primer 3E

In the explicit and special template definition of explicit specialization definition, the keyword template and a pair
Angle brackets (<> A smaller sign and a greater than sign), and then a special definition of the function template, which specifies the Template
The real parameters of the template and the function parameter table and function body. 1. We can also declare the explicit features of a function template without defining them.
2. When declaring or defining the explicit feature of a function template, we cannot save the keyword template in the slightly-specific feature Declaration and the angle brackets after it. The parameter table similar to the local function parameter cannot be omitted from the feature declaration.
3. If the template real parameters can be deduced from the function parameters, the explicit and special parameters of the template can be omitted from the explicit and special declarations.
4.

(30) explicit features of class templates and tratis C ++ primer 3E

(31) provide a special definition for a member of the class template instance

Explicit special definition includes the keyword template followed by a pair of angle brackets (<> A smaller than sign and a greater than sign) and the special definition of Class Members.
(31) Overall special Template

1. The generic class template can be defined only when it is declared (not necessarily defined.
That is, the compiler must know the name of the class template before the template is made special.

2. If the entire class is made special, the symbolic template marked with the special definition can only be placed in the explicit form of the class template.
Before the special definition, the special member definition of the class template cannot start with the symbol template <>.

(32) Some Special Class templates

Or a template, but some template parameters are made special by specific types.

If a class template has more than one template parameter, some users may want to provide a specific template parameter or
Group template real-name parameter-specific class templates instead of all template parameters. That is, some people may want to provide such a model,

It is still a general model, but some template parameters have been replaced by actual types or values.

By using the class template to partially convert partial specialization, this is possible. Compared with the general template definition
For the class version after a specific set of template real parameters are instantiated ", some special features of the class template may be used to define
A more appropriate and efficient version.

1. However, the specific name of the class template is always followed by a real parameter table of the template.
2. Some special template parameter tables only list the parameters that are still unknown to the template parameters.
3. Some specific definitions and general templates are completely unavailable

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.