Jump to content

Template (C++)

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by Jjdawson7 (talk | contribs) at 21:15, 3 June 2008 (Class templates: Refined.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

In computer programming, templates are a feature of the C++ programming language that allow code to be written without consideration of the data type with which it will eventually be used. Templates support generic programming in C++.

Templates are of great utility to programmers in C++, especially when combined with multiple inheritance and operator overloading. The C++ Standard Library provides many useful functions within a framework of connected templates.

Technical overview

There are two kinds of templates: function templates and class templates.

Function templates

A function template behaves like a function that can accept arguments of many different types. For example, the C++ Standard Template Library contains the function template max(x, y) which returns either x or y, whichever is larger. max() could be defined like this:

  template <class a> a max(a x, a y)
  {
    if (y >= x)
      return y;
    else
      return x;
  }

This template function can be invoked as a regular function, as in the following example:

  std::cout << max(3, 7); //outputs 7

For the above example, the compiler first examines the function arguments 3 and 7 and determines that they are integers. Hence, the compiler finds that template type a is of type int for that particular method call. Then, the compiler creates a function in which the method signature is int max(int, int). At runtime, whenever the above example code executes, the executable environment (or virtual machine) instantiates the version of that template function that matches the aforementioned method signature.

Template functions can be defined for arguments of any type for which a concrete function can be created by the compiler. If you have defined your own type, you can use operator overloading to define the meaning of < for your type, thus allowing you to use the max() function.

Template functions, which support both primitive and class types, also allow the user to utilize standard template libraries such as STL. Template libraries can leverage template functions by allowing the user of the library to define types and operators for those types in nearly unlimited ways.

As a counterexample, the standard type complex does not define the < operator because there is no strict order on complex numbers. Therefore max(x, y) will fail with a compile error if x and y are complex values. Likewise, other templates that rely on < cannot be applied to complex data. Unfortunately, compilers historically generate somewhat esoteric and unhelpful error messages for this sort of error. Ensuring that a certain object adheres to a method protocol can alleviate this issue.

Class templates

A class template extends the aforementioned template function concept to classes. Class templates are often used to define the methods and sub-types of generic containers. For example, the STL for C++ has a linked list container called list. The statement list<int> designates or instantiates a linked-list of type int. The statement list<string> designates or instantiates a linked-list of type string.

A class template usually defines a set of generic functions that operate on the type that is specified for that class (i.e., the type between the angle brackets as shown above). The compiler will generate the appropriate function code at compile-time for the template parameter type that appears between the brackets.

Advantages and disadvantages

Some uses of templates, such as the max() function, were previously filled by function-like preprocessor macros. For example, here is a max() macro:

    #define max(a,b)   ((a) < (b) ? (b) : (a))
  • Both macros and templates are expanded at compile time.
    • Macros are always expanded inline; templates can also be expanded as inline functions when the compiler deems it appropriate. Thus both function-like macros and function templates have no run-time overhead.
    • With macros, arguments may be evaluated multiple times, which prevents their use if the arguments are expressions with side-effects (e.g. if they are function calls). Templates do not suffer from this problem, as they are functions in the end -- their arguments are evaluated once, when the function is called.
  • Templates are type-safe. Templates avoid some of the common errors found in code that makes heavy use of function-like macros.
  • Perhaps most importantly, templates were designed to be applicable to much larger problems than macros.

There are three primary drawbacks to the use of templates:

  • Many compilers historically have very poor support for templates, so the use of templates can make code somewhat less portable.
  • Almost all compilers produce confusing, unhelpful error messages when errors are detected in template code. This can make templates difficult to develop and has prompted the inclusion of Concepts in the next C++ standard.
  • Each use of a template may cause the compiler to generate extra code (an instantiation of the template), so the indiscriminate use of templates can lead to code bloat, resulting in excessively large executables.

Generic programming features in other languages

Templates were left out of some C++-based languages, such as Java and C# 1.0, largely due to the problems with templates in C++. These languages have adopted other methods of dealing with the same problems. Java's adoption of generics mimics the behavior of templates, but is technically very different. C# added generics (parameterized types) in .NET 2.0. The generics in Ada predate templates.

Although C++ templates and Java or .NET generics are often considered similar, generics only mimic the very basic behavior of C++ templates[1]. None of the advanced templates features relied on by libraries such as Boost or even the STL for template metaprogramming (explicit or partial specialization, default template arguments, template non-type arguments, template template arguments, ...) are available with generics.

References