본문 바로가기
College Study/C++ (ENG)

[C++] Template Programming (ENG)

by 2den 2022. 1. 2.
728x90

 

Function Template

STL container is also a template. With template, you don't have to write codes in duplicate.

template <typename T>  // typename can be replaced with class (even if it is not a class)
T Add(T a, T b)
{
    return a + b;
}
 

Function template is a template for functions. You can skip the template parameter.

Add <int> (3,10);
Add (3,10);
 

There's not the difference between typename and class, so I'll use typename.

 

 

 

Class Template

template <typename T>
bool MyArray<T>::Add(T data)
{ /*...*/ }

template <typename T>
MyArray<T>::MyArray()
    : mysize(0)
{ /*...*/ }
 

The compiler compiles main.cpp and MyArray.cpp seperately (like at the same time). So like making an inline function, you have to put implementation in the header file.

// MyArray.h
template <typename T>
{
public:
    bool Add(T data);
    // ...
private:
    // ...
}

template <typename T>
bool MyArray<T>::Add(T data)
{ /*...*/ }

template <typename T>
MyArray<T>::MyArray()
    : mysize(0)
{ /*...*/ }
 

You can't skip the template parameter, so you have to write it.

MyArray <int> scores;
 

And it's better to call by reference because T might be a huge object.

bool Add(const T& data);
 

 

How To Define a Constant

#define MAX 3              // it is in a global scope
const int MAX = 3;         // it becomes a part of memory of the object
static const int MAX = 3;  // static initialization is in .cpp
                           // so it allocates memories somewhere else
enum { MAX = 3 };
 

enum is not a class, and a type. It is just the way to name the number.

 

 

 

Class Template Trick

template <typename T, size_t N>
class FixedVector
{
public:
    // ...
    size_t GetCapacity() const;
private:
    T mArray[N];
}

template <typename T, size_t N>
size_t FixedVector<T, N>::GetCapacity() const
{
    return N;
}
 
FixedVector<int, 16> numbers;
 

If more data come than the capacity, it returns false. So to catch it earlier, you can use assert.

 

 

 

Two Template Parameters

std::vector <MyPair<std::string> > students;
 
template <typename T, typename U>
{
    // ...
}

MyPair <std::string, int> // ...
 

It is also possible for the function templates to use two template parameters.

 

 

 

Template Specialization

template <class T, class Allocator>
class std::vector <T, Allocator>{ /*...*/ }

template <class Allocator>
class std::vector <bool, Allocator> { /*...*/ }  // you can save 32 times of memory

template < >
// ...
 
// bit flag example
bool MyArray <bool>::Add(bool data)
{
    if (mSize >= MAX)
    {
        return false;
    }
    if (data)
    {
        mArray |= (1 << mSize++);
    } else {
        mArray &= ~(1 << mSize++);
    }
    return true;
}
 

 

Pros and Cons

Pros

- Runtime speed can be faster.

- Duplicate code with the same data type can be reduced.

- Polymorphism can be guaranteed during compilation.

 

Cons

- Compile speed is slow

- As you add template parameters, the exe file grows larger and slower.

- Harder to read

- Debugging can be a bit weird (for the old version)

 

 

 

Best Practice

Keep generic functions short. Write parts that do not need to be templates as separate functions.

 

For containers it is very suitable:

- A wide variety of types can be stored

 

Non-container:

- Use the templates when dealing with more than three types.

- If you have two, just make two classes.

 

728x90

댓글