C++ 模板编译模式

16.3. Template Compilation Models

When the compiler sees a template definition, it does not generate code immediately. The compiler produces type-specific instances of the template only when it sees a use of the template, such as when a function template is called or an object of a class template is defined.


Ordinarily, when we call a function, the compiler needs to see only a declaration for the function. Similarly, when we define an object of class type, the class definition must be available, but the definitions of the member functions need not be present. As a result, we put class definitions and function declarations in header files and definitions of ordinary and class-member functions in source files.


Templates are different: To generate an instantiation, the compiler must have access to the source
code that defines the template. When we call a function template or a member function of a class
template, the compiler needs the function definition. It needs the code we normally put in the
source files.


Inclusion Compilation Model

In the inclusion compilation model  ,  the compiler must see the definition for any template that is used. Typically, we make the definitions available by adding a #includedirective to the headers that declare function or class templates. That #includebrings in the source file(s) that contain the associated definitions:


// header file utlities.h
#ifndef UTLITIES_H // header gaurd (Section 2.9.2, p. 69)
#define UTLITIES_H
template <class T> int compare(const T&, const T&);
// other declarations
#include "utilities.cc" // get the definitions for compare etc.
#endif
// implemenatation file utlities.cc
template <class T> int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
// other definitions


This strategy lets us maintain the separation of header files and implementation files but ensures that the compiler will see both files when compiling code that uses the templates.


Some, especially older, compilers that use the inclusion model may generate multiple instantiations. If two or more separately compiled source files use the same template, these compilers will generate an instantiation for the template in each file. Ordinarily, this approach implies that a given template will be instantiated more than once. At link time, or during a prelink phase, the compiler selects one instantiation, discarding the others. In such cases, compile-time performance can be significantly degraded if there are a lot of files that instantiate the same template. This compile-time degradation is unlikely to be a problem on modern computers for many applications. However, in the context of large systems, the compile-time hit may become important.


Such compilers often support mechanisms that avoid the compile-time overhead implicit in multiple instantiations of the same template. The way compilers optimize compile-time performance varies from one compiler to the next. If compile time for programs using templates is too burdensome, consult your compiler's user's guide to see what support your compiler offers to avoid redundant instantiations.


Separate Compilation Model

In the separate compilation model  ,  the compiler keeps track of the associated template definitions for us. However, we must tell the compiler to remember a given template definition. We use the export keyword  to do so.


The exportkeyword indicates that a given definition might be needed to generate instantiations in other files. A template may be defined as exported only once in a program. The compiler figures out how to locate the template definition when it needs to generate these instantiations. The  export keyword need not appear on the template declaration.
Ordinarily, we indicate that a function template is exported as part of its definition. We do so by including the keyword exportbefore the templatekeyword:


// the template definition goes in a separately-compiled source file
export template <typename Type>
Type sum(Type t1, Type t2) /* ...*/


The declaration for this function template, should, as usual, be put in a header. The declaration
must not specify export.
Using exporton a class template is a bit more complicated. As usual, the class declaration must go in a header file. The class body in the header should not use the  exportkeyword. If we used export in the header, then that header could be used by only one source file in the program.


Instead, we exportthe class in the class implementation file:
// class template header goes in shared header file
template <class Type> class Queue { ... };
// Queue.ccimplementation file declares Queue as exported
export template <class Type> class Queue;
#include "Queue.h"
// Queue member definitions


The members of an exported class are automatically declared as exported. It is also possible to declare individual members of a class template as exported. In this case, the keyword exportis not specified on the class template itself. It is specified only on the specific member definitions to be exported. The definition of exported member functions need not be visible when the member is used. The definitions of any nonexported member must be treated as in the inclusion model: The definition should be placed inside the header that defines the class template.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值