Still don't understand Templates.

I've seen tutorials, I've read books, and I still don't understand what a template is. I know it's to accept all variable types but I don't know how to implement them and use them. If the little I know of them is correct how would I made the following add() function a template and how would I use it?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Example code
#include <iostream>
#include <conio.h>
using namespace std;

void add(int *x, int *y);
int sum;

int main() {
   int addend1;
   int addend2;
   cout << "Please write first addend: ";
   cin >> addend1;
   cout << "Please write second addend: ";
   cin >> addend2;
   add(&addend1, &addend2);
   cout << "\n\nThe sum is: " << sum << endl;
   _getch();
}

void add(int *x, int *y) {
   sum = *x + *y;
}


Also could you explain to me what templates are?
A template is like a "blueprint".

If you make a function a template... then it's not really a function on it's own. Instead it is a blueprint for which the compiler can make any number of different functions.

For example... with normal functions, you could repeat the function several times:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// a function that works with ints
int add_int(int x, int y)
{
    return (x+y);
}

// one that works with doubles
double add_double(double x, double y)
{
    return (x+y);
}

// one that works with strings (though 'add' is a bit weird)
std::string add_string(std::string x, std::string y)
{
    return (x+y);
}


// using all of them:
int main()
{
    cout << add_int( 5, 10 );               // prints 15

    cout << add_double( 1.23, 3.5 );        // prints 4.73

    cout << add_string( "hi", " there" );   // prints "hi there"
}


Notice how all 3 of these functions are different. add_int only works with ints. add_double only works with doubles, etc.

Also notice that even though all the functions are different... the body for them is all the same:

1
2
3
{
    return (x+y);
}



So... instead of duplicating this function a dozen times so that it will exist for all the different types we want to be able to add... we can just create a template that the compiler can use to create those functions for us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template <typename T>   // <- 'T' can be whatever type.
T add(T x, T y)         // <- so if T==int, then this would be 'int add(int x, int y)'
{                       // ... or if T==string, then this would be 'string add(string x, string y)'
    return (x+y);       // etc
}

// Now that the template is written... we can use it to create any number of functions for us automatically.
//   we don't have to manually create each function.
int main()
{
    cout << sum<int>( 5, 10 );              // <- calls add where T==int.  Prints 15
    cout << sum<double>( 1.23, 3.5 );       // <- calls add where T==double.  Prints 4.73
    cout << sum<string>( "hi", " there" );  // <- calls add where T==string.  Prints "hi there"
    
    /*
        As you can see... we determine what 'T' is by putting it in angle brackets.  IE
        sum<int> makes T==int.
        
        However... we often don't even need to do that.  The compiler can usually figure out what T is
        based on the parameters you give it:
    */
    
    cout << sum( 5, 10 );       // <- since 5 and 10 are both ints... it knows T==int.  We don't have to tell it.
    cout << sum( 1.23, 3.5 );   // <- since 1.23 and 3.5 are both doubles... it knows T==double.
    
    std::string a = "hi";
    std::string b = " there";
    cout << sum( a, b );        // <- since a and b are both strings... it knows T==string
}
Last edited on
Wow, thanks! Looking more into the book I saw that there is a template with the word "class" in it. Like this:

1
2
3
4
5
6
template<class T> class SayHi {
     T data;
public:
    SayHi(T a) : data(a) {}
    void display() { cout << data << endl; }
}


So what basically it's the same thing as this:

1
2
3
4
5
6
class SayHi {
    string data;
public:
    SayHi(string a) : data(a) {}
    void display() { cout << data << endl; }
}


Except it can use whatever type. I would also call it the same way as a normal class, right?

1
2
3
4
5
6
//For template
SayHi sayHi("SUP!");
sayHi.display();
//For normal class
SayHi sayHi("SUP!");
sayHi.display();


They would both work?
No, for classes template argument deduction is not allowed. YOu have to write std::vector<int>, you have to write SayHi<string> in your templated class.
1
2
3
4
5
6
SayHi<string> sayHi("SUP!");
sayHi.display();
SayHi<int> sayHi(42);
sayHi.display();
//SayHi<string> sayHi(0);//Will not compile: 
//sayHi.display();       //int cannot be converted to string
SUP!
42
If you ever used vector, you used templated class. string is actually is a typedef for std::basic_string<char>, so it is a (hidden) templated class too
Last edited on
I haven't reached vectors yet, they're right after templates. Thanks for the help guys.
Excellent explanation, Disch.
Topic archived. No new replies allowed.