Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some confusions in C++ Templates

Tags:

c++

templates

I am right now reading this book , C++ templates : Complete guide. At a para i got stuck couldn't understand the terminology , here is the para:

A fundamental principle is that any template argument must be a quantity or value that can be determined at compile time. As becomes clear later, this requirement translates into dramatic benefits for the run-time costs of template entities. Because template parameters are eventually substituted by compile-time values, they can themselves be used to form compile-time expressions. This was exploited in the ArrayInClass template to size the member array array. The size of an array must be a so-called constant-expression, and the template parameter N qualifies as such.

We can push this reasoning a little further: Because template parameters are compile-time entities, they can also be used to create valid template arguments. Here is an example :

template <typename T> 
class Dozen { 
  public: 
    ArrayInClass<T,12> contents; 
};

Note how in this example the name T is both a template parameter and a template argument. Thus, a mechanism is available to enable the construction of more complex templates from simpler ones. Of course, this is not fundamentally different from the mechanisms that allow us to assemble types and functions.

I am unable to understand anything. I appreciate any help with simple and understanding words a lot.

Edit:

Arrayinclass:

template <typename T, int N> 
class ArrayInClass { 
  public: 
    T array[N]; 
};
like image 525
Mr.Anubis Avatar asked Feb 23 '23 04:02

Mr.Anubis


2 Answers

There are certain expression in C++ that are required to be known at compile time. For example:

int someArray[30];

The 30 must be a compile-time constant in C++. It could have been:

int someArray[30 + 3];

That is fine, because the compiler has all of the information necessary to compute at compile time how big to make the array. However:

void MyFunc(int numItems) {
  int someArray[30 + numItems];
}

This is not a compile-time constant, since the user could call MyFunc with any integer value. The compiler does not know how big to make the array, so this is a compiler error.

(note: C99 allows for the creation of arrays of arbitrary sizes like this. C++ does not).

Because a template parameter is a compile-time value, it is possible to pass it to other places that require compile-time values:

template<int ArrayLen> void MyFunc() {
  int someArray[30 + ArrayLen];
}

This is legal C++ because every use of MyFunc must specify a compile-time integer: the length of the array. You cannot just call MyFunc() you have to call MyFunc<21>(). And since template arguments must be compile-time determinable values, the user himself cannot provide a value that is not compile-time defined.

Because template parameters are always compile-time defined, you can nest templates:

template<int ArrayLen> void OtherFunc {
  MyFunc<ArrayLen + 3>();
}

This new template function calls the old one with an array 3 bigger than what it was given.

like image 141
Nicol Bolas Avatar answered Mar 09 '23 17:03

Nicol Bolas


When the author says that template parameters are eventually substituted by compile time constants, he means just that. For example, in the following very well known example, the generated code is a numeric constant (i.e. the multiplications take place at compile-time, not runtime:

#include <iostream>

template <int N>
struct Factorial
{
    enum { value = N * Factorial<N-1>::value };
};

template <>
struct Factorial<1>
{
    enum { value = 1 };
};

// example use
int main()
{
    std::cout << Factorial<5>::value << endl;
    return 0;
}
like image 36
Kevin Avatar answered Mar 09 '23 17:03

Kevin