Alias Templates and Template Parameters

Alias Templates and Template Parameters

This post is a cross-post from www.ModernesCpp.com.

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.

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. 

No alt text provided for this image

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::list. std::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 (1) 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.

No alt text provided for this image

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, Wolfgang G?rtner, 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, and Satish Vangipuram.

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

My special thanks to Embarcadero

Seminars

I'm happy to give online-seminars or face-to-face seminars world-wide. 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++


 

要查看或添加评论,请登录

Rainer Grimm的更多文章

社区洞察

其他会员也浏览了