templates wtf?

Download Templates WTF?

Post on 15-Jan-2016




0 download

Embed Size (px)


Templates WTF?. [ ]. Available online at: http://www.cs.washington.edu/people/acm/tutorials Prepared for Bart Niswonger’s CSE 326 (Data Structures) class, Su ’01 – Albert Wong (awong@cs). The immortal question: Why?. What exactly are templates for, and why learn them?. - PowerPoint PPT Presentation


  • [ ]TemplatesWTF?Available online at: http://www.cs.washington.edu/people/acm/tutorialsPrepared for Bart Niswongers CSE 326 (Data Structures) class, Su 01 Albert Wong (awong@cs)

  • The immortal question: Why?What exactly are templates for, and why learn them? Limited Generic Programming (polymorphism)Some functions have the same semantic meaning for some (if not all) data types. For instance, a function print() should display a sensible representation of anything passed in. Ideally, it shouldnt need to be rewritten for each possible type.

    Less repetitive codeCode that only differs in the data type it handles does not have to berewritten for each and every data type you want to handle. Its easier toread and maintain since one piece of code is used for everything

    To be a 1337 CXX H@x0RCome on. You know you want to be oneand templates are the justsort of obscure C++ thing that C++ H@x0rs must know about. (That anduser defined casts, mutable data members, etc. etc.)

  • Example: a swap functionStupid method write an overloaded function for each typevoid swap(int &a, int &b) { int c = a; a = b; b = c;}void swap(T &a, T &b) { T c = a; a = b; b = c;}Swap for integersSwap for an arbitrary type Ttemplate void swap(T &a, T &b) { T c = a; a = b; b = c;}This function can be used with any type that supports assignment and can be passed in as a non-const reference. MSVC provides you this function. Its not standard though. (Dont use it! g++ doesnt provide it!)Problem: Oftentimes, it is nice to be able to swap the values of two variables. This functions behavior is similar for all data types. Templated functions let you do that in most cases without any syntax changes.Template method write one templated function

  • Template Syntax: swap dissectedtemplate void swap(T &a, T &b) { T c = a; a = b; b = c;}The template line states that everything in the following declaration or definition is under the subject of the template. (In this case, the definition is the function swap)In here goes a list of placeholders variables. In almost all cases, they will be specified with either the typename or class keywords. These two keywords are equivalent. Placeholder variables have one value within each template declaration. Think of them as being replaced by whatever type you specify the template to be.Template behavior:Like most things in C++, templates attempt to behave as if it were a natural part of the language. It fails.There are two ways to use templates, implicit and explicit specialization. Explicit specialization always works. Implicit sometimes works. Why ever use implicit specialization? Its much cleaner. What are they? That is explained on the next slide.

  • Template Syntax: Using ittemplate void swap(T &a, T &b) { T c = a; a = b; b = c;}To use a template, one has to specialize it. This is why it isnt quite a generic function. It does static polymorphism. It morphs itself to the right type during preprocess time (explained later!).To explicitly specialize a template, write its name with the arguments for the placeholder variables in angle brackets. This method always works. Example: double d1 = 4.5, d2 = 6.7; swap(d1, d2);Templates however can auto-sense its placeholder values if all information about what the placeholders represent can be inferred from its context (arguments, and for member functions, the associated class instance). This is called implicit specialization. In the previous case, the compiler is smart enough to figure out that T is a double even without the explicit since the arguments are doubles. Thus this shorthand works: Example: swap(d1, d2);Using a templateSyntax

  • How they Work: Compilation 098PreprocessorResolves #define, #include, comments, templatesCompilerTranslates code to Machine Language. It outputs an object file. This code is not executableLinkerTakes object files and resolves references to functions and variables in different filesIn MSVC, all these steps are hidden behind a button with a red exclamation mark. This is bad. A compiler has at least 2 portions, and in C++ it has 3 portions. When you build an executable from a C++ source file, the preprocessor removes all the things listed under Preprocessor. The result is pure C++ code (no comments, templates, #includes, etc). This code is then compiled and linked.All good programmers understand this process well.Preprocessor.c.h.c.hCompilerLinkerexecutableLibrariesSource code (text)C/C++ code (text)Object code (bin)Native Executable (bin)

  • How they Work: Compiler, LinkerThe term compile is somewhat ambiguous. Often, when people say compile they mean build. In the formal sense, it means turning one language into another language. With C++, this generally means turning C++ source code into Machine Code.Each C++ source file is usually compiled into an object file that contains the code of all its defined functions. At this point, if you call a function from a library or another file, the object code (stuff in the object file) only says this function exists somewhere and I want to use itThis if formally what the compiler is. When you get syntax errors, this is usually the compiler talking to you (as opposed to the linker or preprocessor).What does it mean to compile?After compilation happens, all the object files need to be linked together into a final executable. All I want this function stubs in the object files have to actually be resolved to some block of machine code and then the resulting executable has to be formatted in a way the operating system can understand.If you write a prototype for a function, but forget to define it, your code will compile but it wont link. Link errors are usually harder to track, as the linker cant always give you line numbers (the linker only looks at the object files and knows nothing about the original source.What does it mean to link?

  • How they Work: PreprocessorWhat is the preprocessor?The preprocessor, formally, deals with the directives that start with a # sign (like #include, #define). However, here, the term will be used to mean everything that happens before the compiler gets the stuff to turn into machine code.The relevant (in relation to templates) things the preprocessor does are: Replaces all #include statements and with the files they refer to. Removes all comments. Replaces all #defines macros with their value Generates actual code from templatesTemplates do not exist! (there is no spoon)Templates are a preprocessor construct. They are cookie-cutters with which the preprocessor generates real C++ code. When a template is used, (that is, specialized, implicitly or explicitly), it get instantiated.The instantiation tells the preprocessor to create a version of the template where each placeholder is replaced by its specialization. At this point, the specific version of the template comes into existence and can be compiled. It does not exist otherwise!In a very real way, a template just does a search and replace for each type you specialize the template for. In essence, you are doing the same as writing a bunch of overloaded functions. Its just done for you, behind your back.

  • How they Work: ConsequencesProblem:Templates are resolved in the preprocessing stage, so they dont exist to the compiler until they get instantiated. This is the balance between trying to make templates work transparently, and trying to make things efficient. As usual, C++ fails and just makes things inconsistent.Effects:Template code will not get compiled until used (and thus instantiated). Thus, the compiler will not catch syntax errors until the template is used.A specialization (a place you actually use the template) instantiates all relevant templates before it. If a template appears after a specialization, it doesnt get instantiated, and thus, it is not compiled.Conclusion:To make things work, all relevant template definitions must appear before at least one specialization. Otherwise, parts of the template will not get instantiated and compiled.Fixes:There are ways to deal with this. They will be introduced later. But first, let us journey to the pits of hellerrI mean templated classes

  • Class Templates: Class DefinitionSyntax:Templated classes basically follow same syntax as templated functions. However, the rules for which templated classes can infer their specialization (see Template Syntax) are a bit more convoluted.Before moving on, a bit of review on templated functions:Are the following two templates equivalent?template void swap(T &a, T &b) { T c = a; a = b; b = c;}template void swap(C &a, C &b) { C c = a; a = b; b = c;}Answer:Yes, they are equivalent. This may be relevant when writing class templates as it is possible that a situation may arise where two definitions are written for the same thing. If this happens, the program will not build since there are two equivalent function definitions. The name of the placeholder doesnt matter, and typename and class can be used interchangeably. Just something to remember.

  • Class Templates: ExampleExample: A templated, dynamic, 2 dimensional array (Matrix)*#ifndef MATRIX_H#define MATRIX_H

    template class Matrix {public: Matrix(int rows, int cols); Matrix(const Matrix &other); virtual ~Matrix();

    Matrix& operator=(const Matrix &rhs); T* operator[](int i); int getRows() const; int getCols() const;

    protected: void copy(const Matrix &other);

    private: Matrix(); int m_rows; int m_cols; T *m_linArray;};

    #endif /* MATRIX_H */File: Matrix.hNotice the only addition to the class definition is the line: template *A commented version of this code is provided