C++.in.a.Nutshell [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

C++.in.a.Nutshell [Electronic resources] - نسخه متنی

Ray lischner

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید












7.10 Compiling Templates


Like
an ordinary function, a function template requires a definition
before the function can be called. Like an ordinary class, a class
template requires a definition for each member function and static
data member before they can be used. Unlike ordinary functions or
members, however, templates are typically defined in every source
file.

Templates are often used by placing a template declaration and all
supporting definitions in a header file, (e.g.,
template.h). Then #include
that file anywhere the template is needed. For every implicit or
explicit instantiation, the compiler generates the necessary code for
the template's instantiation. If multiple source
files instantiate the same template with the same arguments, the
compiler and linker ensure that the program contains a single copy of
the instantiated functions and members.

Different compilers use different techniques to ensure that the
program contains a single copy of each template instance. The
following are four different approaches:


  • The most common approach is to have the compiler keep track of which
    source files require which instantiations. When the program is
    linked, the compiler combines all the lists of required
    instantiations and compiles the template instantiations at that time.
    As an optimization, the compiler saves the compiled instantiations,
    so an instantiation that does not change does not need to be
    recompiled.


  • Another approach is to have the compiler generate the code for all
    needed instantiations when it compiles each source file. The linker
    identifies duplicate instantiations and ensures that the linked
    program gets a single copy of each instantiation.


  • A third approach is to separate the template declaration from its
    associated definitions. If the declaration is in
    template.h, the definitions are in
    template.cc. The compiler automatically locates
    the definition file from the name of the declaration file. In this
    scenario, the compiler keeps track of which instantiations it needs
    and compiles each of them only once.


  • Another approach uses the export keyword to
    declare and define templates. An exported template lets you define a
    function template or all the members of a class template in a
    separate source file. The template's header contains
    only the declarations.

    As I write this, exactly one compiler supports
    export. (See the book's web site
    for current details.) Major compiler vendors are finally moving
    toward full conformance with the standard, including
    export. Nonetheless, I doubt
    export will see widespread support, at least for
    the next few years.

    If portability is important to you, do not use
    export.



Consult your compiler's documentation to learn how
it handles templates. When writing a template that can be used by
multiple compilers, a common technique is to put the declaration in a
header file (e.g., template.h), and the
definitions in another file (e.g., template.cc),
and at the end of template.h, use conditional
directives to #include
"template.cc" for those compilers where it is
needed. Use conditional compilation to define a macro only for
compilers that support export. Example 7-18 shows this common pattern.

Example 7-18. Declaring and defining a template

// point.h
#ifndef POINT_H
#define POINT_H
#ifdef HAS_EXPORT
#define EXPORT export
#else
#define EXPORT
#endif
EXPORT template<typename T>
class point {
public:
point(T a, T b);
point( );
T x( ) const { return x_; }
T y( ) const { return y_; }
private:
T x_, y_;
};
#ifdef NEED_TEMPLATE_DEFINITIONS
#include "point.cc"
#endif
#endif // POINT_H
// point.cc
#include "point.h"
EXPORT template<typename T>
point<T>::point(T a, T b)
: x_(a), y_(b)
{}
EXPORT template<typename T>
point<T>::point( )
: x_(T( )), y_(T( ))
{}
// program.cc
#include "point.h"
int main( )
{
point<float> ptf;
point<int> pti;
...
}

If your compiler supports export, define
HAS_EXPORT. If the compiler requires template
definitions in every source file, define
NEED_TEMPLATE_DEFINITIONS. Most compilers offer a
way to define macros globally (e.g., in a project definition file, in
a makefile, etc.). Another alternative is to use conditional
compilation to test the predefined macros that most compilers define,
and use those to set the template macros accordingly. Put these
definitions in a configuration file that is included first by every
other file, as shown in Example 7-19.

Example 7-19. Configuring template compilation macros

// config.h
#ifndef CONFIG_H
#define CONFIG_H
#ifdef _ _COMO_ _
#define HAS_EXPORT
#undef NEED_TEMPLATE_DEFINITIONS
#endif
#if defined(__BORLANDC__) || defined(_ _GNUC_ _)
#undef HAS_EXPORT
#define NEED_TEMPLATE_DEFINITIONS
#endif
...
#endif // CONFIG_H



    / 270