Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

C++ Templates 2


Published on

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

C++ Templates 2

  1. 1. Overview Overview Understanding C++ Templates his article is a follow-up to the In this article, we’ll learn the basic syntax and T ‘An Introduction to C++ semantics of the features in the templates in C++ and Templates’ article published in the October issue of LFY. So, write small programs. without further ado, let’s get started. Class and function templates There are two kinds of templates: function templates and class templates. To define a template, use the template keyword with the template parameters given within ankle brackets, and provide the class or function definition after that. For example: // array_container is a ‘class template’ template <class T> class array_container { T arr[10]; // other members }; // generic swap is a ‘function template’ template <class Type> void swap(Type &t1, Type &t2) { Type temp = t1; t1 = t2; t2 = temp; } The conventional names typically used for template-type arguments are T and Type, but it can be any valid variable name. Template instantiation We can ‘use’ the template by providing necessary arguments, which is known as instantiating the template. An instance created from that template is a template instantiation. For class templates, we have to explicitly provide the instantiation arguments. For function templates, we can explicitly provide the template arguments or else the 88 NOVEMBER 2007 | LINUX FOR YOU | CMYK
  2. 2. Overview compiler will automatically infer the template arguments T arr[size]; from the function arguments. public: For example, here is how we can instantiate the int getLength() { array_container and swap templates: return size; } // type arguments are explicitly provided // other members array_container<int> arr_int; }; float i = 10.0, j = 20.0; array_container<float, 10> arr_flt; // compiler infers the type of argument as float and cout<<“array size is “ << arr_flt.getLength(); // implicitly instantiates swap<float>(float &, float &); // prints: array size is 10 swap(i, j); // or explicitly provide template arguments like this: // swap<float>(i, j); Implicit instantiation and type inference cout<<“after swap : “<< i << “ “ << j; The implicit inference of function templates is very // prints after swap : 20 and 10 convenient to use; the users of the template need not even know that it is a template (well, in most cases), and use it as if it were an ordinary function. This is a powerful Template parameters feature, particularly when used with function overloading. Template parameters are of three types: type parameters, We’ll look at a simple example for inference of template non-type parameters and template-template parameters. parameters here: Type parameters are used for abstracting the type details in data-structures and algorithms. Non-type parameters // the types T and SIZE are implicitly inferred from the are used for abstracting the values known at compile-time // use of this function template itself. A template itself can be passed as a parameter to template<typename T, int SIZE> another template, which is a template-template parameter. int infer_size(T (*arr)[SIZE]) { We’ve already seen an example for type parameters, and return SIZE; we’ll cover non-type parameters in the next section. } Template-template parameters are not covered in this article as it’s an advanced topic. int main() { Type parameters can be declared with class or int int_arr[] = {0, 1} ; typename keywords and both are equivalent. Using the char literal[] = “literal”; keyword class for a template type parameter can be a little cout<<“length of int_arr: “<<infer_size(&int_arr)<<endl; confusing, since the keyword class is mainly used for cout<<“length of literal: “<<infer_size(&literal)<<endl; declaring a class; so it is preferable to use the typename } keyword for type parameters. For example: // prints // instead of template <class T> use // length of int_arr: 2 template <typename T> // length of literal: 8 class array_container; In this program, the type and non-type parameters are Template non-type parameters automatically inferred from the instantiation of infer_size. Non-type parameters are used for abstracting constant The first instantiation is for the integer array of Size 2. The values in a template class. Non-type parameters cannot be T in infer_size is inferred as int and SIZE as 2. Similarly, of floating-point type. Also, the value of a non-type for the string literal, it becomes char and 8. parameter should be known at the compile-time itself as templates are a compile-time mechanism and template Template specialisation instantiation is done by the compiler. A template is to provide the description for the generic In the array_container template we saw earlier, we implementation of a class or a function. For specific types abstracted the type of the array and hard-coded the size of (or values, in case of non-type parameters), the template the array. It will be flexible if we can change the size of the is instantiated or specialised. For class and function array for different uses. Non-type parameters come handy templates, specialisation results in class and function for purposes like this: definitions. Such generated class and function definitions can be used just like any other class or function definitions template <class T, int size> (they are ‘first class citizens’). If you want to provide a class array_container { specific implementation for particular types (or values in | LINUX FOR YOU | NOVEMBER 2007 89 CMYK
  3. 3. Overview case of non-type arguments), you can explicitly provide a t1.swap(t2); specialised implementation; this is known as explicit } specialisation. In case an instantiation is needed for those particular int main() { types or values, instead of creating a class or function int i = 20, j = 10; definition from the template, if any of the explicit // compiler instantiates swap<int>(int &, int &) specialisations match, it will be used. swap(i, j); Consider that the user-defined class my_vector has a my_vector v1(20), v2(10); member swap that provides an efficient implementation // however, for my_vector, the specialization is used for swapping two my_vectors. If a swap function with two swap(v1, v2); arguments passing my_vector instances are passed, we } prefer to call my_vector::swap instead, using the code in the general swap template. Here is how we can do it: When the explicit specialisation has one or more parameters that still depend on the type or non-type // generic swap is a ‘function template’ parameters of the primary template, it is referred to as template <class Type> partial specialisation. void swap(Type &t1, Type &t2) { C++ templates is a very powerful feature, but it is also Type temp = t1; complex and it takes time to learn the features and master t1 = t2; it. In this article, we had a brief overview of the features of t2 = temp; the templates in C++, which is a good starting point for } exploring it further. // explicit specialization for swapping my_vector’s By: S.G. Ganesh is a research engineer in Siemens template <> (Corporate Technology). He has authored a book “Deep C” void swap(my_vector &t1, my_vector &t2) { (ISBN 81-7656-501-6). You can reach him at // call my_vector::swap for swapping two my_vector’s 90 NOVEMBER 2007 | LINUX FOR YOU | CMYK