Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

#include <iostream>

template<size_t idx, typename T> struct GetHelper;

template<typename ... T> struct DataStructure

{

};

template<typename T, typename ... Rest> struct DataStructure<T, Rest ...>

{

DataStructure(const T& first, const Rest& ... rest) : first(first)

, rest(rest...)

{}

T first;

DataStructure<Rest ... > rest;

template<size_t idx> auto get()

{

return GetHelper<idx, DataStructure<T,Rest...>>::get(*this);

}

};

template<typename T, typename ... Rest>

struct GetHelper<0, DataStructure<T, Rest ... >>

{

static T get(DataStructure<T, Rest...>& data)

{

return data.first;

}

};

template<size_t idx, typename T, typename ... Rest> struct GetHelper<idx, DataStructure<T, Rest ... >>

{

static auto get(DataStructure<T, Rest...>& data)

{

return GetHelper<idx-1, DataStructure<Rest ...>>::get(data.rest);

}

};

int main()

{

DataStructure<int, float, std::string> data(1, 2.1, "Hello");

std::cout << data.get<0>() << std::endl; std::cout << data.get<1>() << std::endl; std::cout << data.get<2>() << std::endl;

return 0;

}

Section 77.4: Argument forwarding

Template may accept both lvalue and rvalue references using forwarding reference:

GoalKicker.com – C++ Notes for Professionals

417

template <typename T> void f(T &&t);

In this case, the real type of t will be deduced depending on the context:

struct X { };

X x;

f(x); // calls f<X&>(x) f(X()); // calls f<X>(x)

In the first case, the type T is deduced as reference to X (X&), and the type of t is lvalue reference to X, while in the second case the type of T is deduced as X and the type of t as rvalue reference to X (X&&).

Note: It is worth noticing that in the first case, decltype(t) is the same as T, but not in the second.

In order to perfectly forward t to another function ,whether it is an lvalue or rvalue reference, one must use std::forward:

template <typename T> void f(T &&t) {

g(std::forward<T>(t));

}

Forwarding references may be used with variadic templates:

template <typename... Args> void f(Args&&... args) {

g(std::forward<Args>(args)...);

}

Note: Forwarding references can only be used for template parameters, for instance, in the following code, v is a rvalue reference, not a forwarding reference:

#include <vector>

template <typename T>

void f(std::vector<T> &&v);

Section 77.5: Partial template specialization

In contrast of a full template specialization partial template specialization allows to introduce template with some of the arguments of existing template fixed. Partial template specialization is only available for template class/structs:

// Common case: template<typename T, typename U> struct S {

T t_val;

U u_val;

};

// Special case when the first template argument is fixed to int template<typename V>

struct S<int, V> {

double another_value;

int foo(double arg) {// Do something}

GoalKicker.com – C++ Notes for Professionals

418

};

As shown above, partial template specializations may introduce completely di erent sets of data and function members.

When a partially specialized template is instantiated, the most suitable specialization is selected. For example, let's define a template and two partial specializations:

template<typename T, typename U, typename V> struct S {

static void foo() {

std::cout << "General case\n";

}

};

template<typename U, typename V> struct S<int, U, V> {

static void foo() { std::cout << "T = int\n";

}

};

template<typename V> struct S<int, double, V> {

static void foo() {

std::cout << "T = int, U = double\n";

}

};

Now the following calls:

S<std::string, int, double>::foo();

S<int, float, std::string>::foo();

S<int, double, std::string>::foo();

will print

General case

T = int

T = int, U = double

Function templates may only be fully specialized:

template<typename T, typename U> void foo(T t, U u) {

std::cout << "General case: " << t << " " << u << std::endl;

}

// OK. template<>

void foo<int, int>(int a1, int a2) {

std::cout << "Two ints: " << a1 << " " << a2 << std::endl;

}

void invoke_foo() {

foo(1, 2.1); // Prints "General case: 1 2.1" foo(1,2); // Prints "Two ints: 1 2"

}

GoalKicker.com – C++ Notes for Professionals

419

// Compilation error: partial function specialization is not allowed. template<typename U>

void foo<std::string, U>(std::string t, U u) {

std::cout << "General case: " << t << " " << u << std::endl;

}

Section 77.6: Template Specialization

You can define implementation for specific instantiations of a template class/method.

For example if you have:

template <typename T>

T sqrt(T t) { /* Some generic implementation */ }

You can then write:

template<>

int sqrt<int>(int i) { /* Highly optimized integer implementation */ }

Then a user that writes sqrt(4.0) will get the generic implementation whereas sqrt(4) will get the specialized implementation.

Section 77.7: Alias template

Version ≥ C++11

Basic example:

template<typename T> using pointer = T*;

This definition makes pointer<T> an alias of T*. For example:

pointer<int> p = new int; // equivalent to: int* p = new int;

Alias templates cannot be specialized. However, that functionality can be obtained indirectly by having them refer to a nested type in a struct:

template<typename T>

struct nonconst_pointer_helper { typedef T* type; };

template<typename T>

struct nonconst_pointer_helper<T const> { typedef T* type; }; template<typename T> using nonconst_pointer = nonconst_pointer_helper<T>::type;

Section 77.8: Explicit instantiation

An explicit instantiation definition creates and declares a concrete class, function, or variable from a template, without using it just yet. An explicit instantiation can be referenced from other translation units. This can be used to avoid defining a template in a header file, if it will only be instantiated with a finite set of arguments. For example:

// print_string.h template <class T>

void print_string(const T* str);

GoalKicker.com – C++ Notes for Professionals

420