Term
What do templates do in C++, and how are they a form of "meta"programming? |
|
Definition
Templates let you write generic that works with all data types.
At pre-compilation, templates generate intermediate code for the data types used for a template |
|
|
Term
function template
What do you expect the output to be?
template <typename T> T f(const T& t) { return t + t ; }
int main() { cout << f(10) << endl; cout << f(1.3f) << endl; cout << f('a') << endl; cout << f(string("BA")) << endl; return 0 ; }
|
|
Definition
20 2.6 ┬ BABA
f('a') is working as expected... but I dont like like |
|
|
Term
template <typename T> T f(const T& t) { return t + t ; }
template<> char f(const char& c) { if (c >= 'a' && c <= 'z') { return c - ('a' - 'A'); } else { return c; } }
int main() { cout << f(10) << endl; cout << f(1.3f) << endl; cout << f('a') << endl; cout << f(string("BA")) << endl;
return 0 ; }
|
|
Definition
|
|
Term
Will this code work? If not why?
Vector.h
#ifndef VECTOR_H #define VECTOR_H #include <iostream>
template <typename T> class Vector { T x, y, z;
public: Vector(T x, T y, T z); ~Vector();
friend std::ostream& operator<<(std::ostream& os, const Vector<T>& vec);
}; #endif //VECTOR_H
Vector.cpp
#include "Vector.h"
template<typename T> Vector<T>::Vector(T x, T y, T z) : x(x), y(y), z(z) {}
template<typename T> Vector<T>::~Vector(){}
template<typename T> std::ostream& operator<<(std::ostream& os, const Vector<T>& vec) { os << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")"; return os; }
main.cpp
#include "Vector.h"
int main(){ Vector<int> P(1,2,3); std::cout << P; }
|
|
Definition
ERROR
Template definition and declaration code should all be found in one place (translation unit).
When main calls Vector<int> it is looking for the function definitions in Vector.h, but theyre in Vector.cpp
|
|
|
Term
Does this fix the issue?
Vector.h
#ifndef VECTOR_H #define VECTOR_H #include <iostream>
template <typename T> class Vector { T x, y, z;
public: Vector(T x, T y, T z) : x(x), y(y), z(z) {} // Constructor inline ~Vector() {} // Destructor inline
friend std::ostream& operator<<(std::ostream& os, const Vector<T>& vec) { os << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")"; return os; } };
#endif //VECTOR_H
main.cpp
#include "Vector.h"
int main(){ Vector<int> P(1,2,3); std::cout << P; }
|
|
Definition
|
|
Term
If you want to restrict T to floats and ints, you can define them in the .cpp file
#include "Stack.h"
template class Stack<int>; template class Stack<float>;
what will happen if you did Stack<*int>?
#include "Stack.h"
int main(){ Stack<*int> stack; }
|
|
Definition
ERROR
T can be a int but not a *int
You can do Stack<int>* stack. (This is obv not the same as having a stack of int pointers) |
|
|
Term
Will this work?
#ifndef VECTOR_H #define VECTOR_H
template <typename T> class Item { int id; T item;
public: static int counter; static T default_item;
Item(): id(++counter) , item(default_item) {} Item(T item): id(++counter), item(item) {} }; #endif //VECTOR_H
main.cpp
int main(){ Item<int> item; }
|
|
Definition
NO
Static members still need to be declared outside the class declaration
Each T type member needs a separate definition.
|
|
|
Term
Will this work?
#ifndef VECTOR_H #define VECTOR_H #include <iostream>
template <typename T> class Item { int id; T item;
public: static int counter; static T default_item;
Item(): id(++counter) , item(default_item) {} Item(T item): id(++counter), item(item) {} };
template <typename T> int Item<T>::counter = 0;
template <> int Item<int>::default_item = 0; template <> char Item<char>::default_item = 'a';
#endif //VECTOR_H
|
|
Definition
Yes
we need the T here to generalize for all T types
template <typename T> int Item<T>::counter = 0;
We need template<> for explicit specialization
template <> int Item<int>::default_item = 0; template <> char Item<char>::default_item = 'a';
|
|
|