Alias Templates and Template Parameters

Contents[Show]

Today, I write about two topics: alias templates and template parameters. Alias templates are a way to give a name to a family of types. Template parameters can be types, non-types, and templates themselves.

 templatesParameters

Let's start with the alias templates.

Alias Templates

With C++11, we got alias templates. Alias templates provide a means to give a convenient name to a family of types. The following code snippet presents the idea for the class template Matrix.

template <typename T, int Line, int Col>
class Matrix{
    ....
};

 

Matrix has three template parameters. The type parameter T, and the non-type parameters Line, and Col (I write about template parameters in the next section.)

For readability, I want to have two special matrices: a Square and a Vector. A Square's number of lines and columns should be equal. A Vector's line size should be one. Thanks to type aliases, I can express my ideas directly in code.

template <typename T, int Line>
using Square = Matrix<T, Line, Line>; // (1)

template <typename T, int Line>
using Vector = Matrix<T, Line, 1>;    // (2)

 

The keyword using ((1) and (2)) declares a type alias. While the primary template Matrix can be parametrized in the three dimensions T, Line, and Col, the type aliases Square and Vector reduce the parametrization to the two dimensions T and Line. From this point of view, alias templates enable it to create intuitive names for partially bound templates. Using Square and Vector is straightforward.

Matrix<int, 5, 3> ma;
Square<double, 4> sq;
Vector<char, 5> vec;

 

A nice use-case of alias templates is the type-traits library.

Type-Traits Library

When you apply std::move(arg) on a value arg, the compiler uses typically std::remove_reference to remove a reference from the underlying type:

static_cast<std::remove_reference<decltype(arg)>::type&&>(arg);   // (1)

static_cast<std::remove_reference_t<decltype(arg)>&&>(arg);       // (2)

 

Thanks to alias templates, version (line 2) is valid since C++14. The following helper type is available:

template< class T >
using remove_reference_t = typename remove_reference<T>::type;

 

Of course, the corresponding helper types for the other functions of the type-traits library returning a type are also available with C++14.

 

The previously defined class template Matrix uses the two non-type template parameters Line and Col.

Template Parameters

 Template parameters can be types, non-types, and templates themselves.

Types

Okay, types are the most often used template parameters. Here are a few examples:

std::vector<int> myVec;
std::map<std::string, int> myMap;
std::lock_guard<std::mutex> myLockGuard;

Non-Types

Non-types can be a

  • lvalue reference
  • nullptr
  • pointer
  • enumerator of a enum
  • integral values
  • floating-point values (C++20)

Integral values are the most used non-types. std::array is the typical example because you have to specify at compile time the size of a std::array:

std::array<int, 3> myArray{1, 2, 3};

Templates

Templates themself can be template parameters. Their definition may look a bit weird.

// templateTemplateParameters.cpp

#include <iostream>
#include <list>
#include <vector>
#include <string>

template <typename T, template <typename, typename> class Cont >    // (1)
class Matrix{
public:
  explicit Matrix(std::initializer_list<T> inList): data(inList) {  // (2)
    for (auto d: data) std::cout << d << " ";
  }
  int getSize() const{
    return data.size();
  }

private:
  Cont<T, std::allocator<T>> data;                                  // (3)                               

};

int main(){

  std::cout << '\n';

                                                                    // (4)
  Matrix<int, std::vector> myIntVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
  std::cout << '\n';
  std::cout << "myIntVec.getSize(): " << myIntVec.getSize() << '\n';

  std::cout << std::endl;

  Matrix<double, std::vector> myDoubleVec{1.1, 2.2, 3.3, 4.4, 5.5}; // (5)
  std::cout << '\n';
  std::cout << "myDoubleVec.getSize(): "  << myDoubleVec.getSize() << '\n';

  std::cout << '\n';
                                                                    // (6)
  Matrix<std::string, std::list> myStringList{"one", "two", "three", "four"};  
  std::cout << '\n';
  std::cout << "myStringList.getSize(): " << myStringList.getSize() << '\n';

  std::cout << '\n';

}

 

Matrix is a simple class template, that can be initialized by a std::initializer_list (line 2). A Matrix can be used with a std::vector (line 4 and line 5), or a std::list (line 6) to hold its values. So far, nothing special. 

templateTemplateParameters

But hold, I forget to mention line 1 and line 3. Line 1 declares a class template that has two template parameters. Okay, the first parameter is the type of the elements and the second parameter stands for the container. Let's have a closer look at the second parameter: template <typename, typename> class Cont >. This means the second template argument should be a template requiring two template parameters. The first template parameter is the type of elements the container stores and the second template parameter is the defaulted allocator a container of the standard template library has. Even the allocator has a default value such as in the case of a std::vector. The allocator depends on the type of elements.

template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

 

Line 3 shows the usage of the allocator in this internally used container. The matrix can use all containers, which are of the kind: container< type of the elements, allocator of the elements>. This is true for the sequence containers such as std::vector, std::deque, or std::liststd::array and std::forward_list would fail because std::array needs an additional non-type for specifying its size at compile-time and std::forward_list does not support the size method.

Maybe you don't like the keyword class for the name of the template template parameter. With C++17, you can replace class with typename:

 

template <typename T, template <typename, typename> class Cont >    // (1)
class Matrix;

template <typename T, template <typename, typename> typename Cont > // (2) 
class Matrix;

 

Line (2) is valid since C++17 and equivalent to line (1).

The Next pdf Bundle: Coroutines

In the post "Which pdf bundle do you want? Make your choice!" you decided for the coroutines bundle.

pollResult

I'm still in the process of preparing the bundle but it should be available in the next few days.

If you subscribe to the English newsletter, you automatically get the link to the current pdf bundle. Have a look at the right top corner of this page. This automatism makes it quite comfortable for me. People that are already subscribed to my newsletter get the link automatically.

What's next?

In my next post, I write about template arguments. It is quite interesting how the compiler deduces the types. The rules do not only apply to function templates (C++98) but also to auto (C++11), to class templates (C++17), and concepts (C++20).

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Dimitrov Tsvetomir, Leo Goodstadt, Eduardo Velasquez, John Wiederhirn, and Yacob Cohen-Arazi.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Said Mert Turkal.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

New

Contact Me

Modernes C++,

RainerGrimmSmall

 

Comments   

0 #1 Paul Topping 2021-06-07 15:35
These code snippets would read better if more attention was paid to names. Wouldn't Square be better named as SquareMatrix? And what do the template parameters Line and Col really mean? Since they are int, I have to assume you really mean NumRows and NumCols, right? I guess I would be ok with Rows and Cols with the plural indicating that they are a count and not the type of a row or column.
Quote
0 #2 Yacob Cohen-Arazi 2021-06-07 16:13
Is there a typo in this sentence ?
Line (1) is valid since C++17 and equivalent to line (1).
?
Quote

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 4444

Yesterday 8323

Week 37324

Month 110734

All 7173024

Currently are 212 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments