Программирование. Variadic Templates. LSP

Содержание

Слайд 2

Содержание Variadic templates Perfect Forwarding LSP

Содержание

Variadic templates
Perfect Forwarding
LSP

Слайд 3

Variadic Templates Объявление переменного числа типов template Объявление набора параметров типов,

Variadic Templates

Объявление переменного числа типов
template
Объявление набора параметров типов, заданных

Args
double f(Args... args)
Распаковка кортежа параметров
g(args...);
Слайд 4

Распаковка кортежа template void f(Us... pargs) {} template void g(Ts... args)

Распаковка кортежа

template void f(Us... pargs) {}
template void g(Ts... args)

{
f(&args...); // “&args...” is a pack expansion
// “&args” is its pattern
}
g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3
// &args... expands to &E1, &E2, &E3
// Us... pargs expand to int* E1, double* E2, const char** E3
Слайд 5

Распаковка кортежа (2) f(&args...); // expands to f(&E1, &E2, &E3) f(n,

Распаковка кортежа (2)

f(&args...); // expands to f(&E1, &E2, &E3)
f(n, ++args...); //

expands to f(n, ++E1, ++E2, ++E3);
f(++args..., n); // expands to f(++E1, ++E2, ++E3, n);
f(const_cast(&args)...);
// f(const_cast(&X1), const_cast(&X2), const_cast(&X3))
f(h(args...) + args...); // expands to
// f(h(E1,E2,E3) + E1, h(E1,E2,E3) + E2, h(E1,E2,E3) + E3)
Слайд 6

Распаковка кортежа (3) (const args&..) // -> (const T1& arg1, const

Распаковка кортежа (3)

(const args&..) // -> (const T1& arg1, const T2&

arg2, ...)
((f(args) + g(args))...) // -> (f(arg1) + g(arg1), f(arg2) + g(arg2), ...)
(f(args...) + g(args...)) // -> (f(arg1, arg2,...) + g(arg1, arg2, ...))
Слайд 7

Использование лямбда template void f(Args... args) { auto lm = [&,

Использование лямбда

template
void f(Args... args) {
auto lm = [&, args...]{

return g(args...); };
lm();
}

Список захвата лямбда-функции может принимать кортеж типов

Слайд 8

Пример: Сумма template double sum(T t) { return t; } //

Пример: Сумма

template
double sum(T t) {
return t;
}
// Рекурсия: поэлементная

развертка кортежа
template
double sum(T t, Rest... rest) {
return t + sum(rest...);
}
Слайд 9

Пример №2 template T square(T t) { return t * t;

Пример №2

template
T square(T t) { return t * t;

}
// Our base case just returns the value.
template
double power_sum(T t) { return t; }
// Our new recursive case.
template
double power_sum(T t, Rest... rest) {
return t + power_sum(square(rest)...);
}

power_sum(2.0, 4.0, 6.0);

Слайд 10

Принцип LSP class Rectangle { public: void SetWidth(int w) { w_

Принцип LSP

 

class Rectangle
{
public:
void SetWidth(int w) { w_ = w; }

void SetHeight(int h) { h_ = h; }
protected:
int w_;
int h_;
};
Слайд 11

LSP: Пример Геометрические фигуры: прямоугольник, квадрат Квадрат – более «специализированное» определение

LSP: Пример

Геометрические фигуры: прямоугольник, квадрат
Квадрат – более «специализированное» определение прямоугольника
Методы Set/GetWidth,

Set/GetHeight, GetArea()
Квадрат –> w == h ?

Rectangle

Quad

Слайд 12

LSP: Реализация Rectangle (1) class Rectangle { public: void SetWidth(int w)

LSP: Реализация Rectangle (1)

class Rectangle
{
public:
void SetWidth(int w) { w_ =

w; }
void SetHeight(int h) { h_ = h; }
int GetArea() { return w_ * h_; }
protected:
int w_;
int h_;
};

Невиртуальные методы не будут корректно работать для Quad

Слайд 13

LSP: Реализация Rectangle (2) class Rectangle { public: virtual void SetWidth(int

LSP: Реализация Rectangle (2)

class Rectangle
{
public:
virtual void SetWidth(int w) { w_

= w; }
virtual void SetHeight(int h) { h_ = h; }
int GetArea() { return w_ * h_; }
protected:
int w_;
int h_;
};

С точки зрения семантики класса эти методы НЕ ДОЛЖНЫ БЫТЬ виртуальными

Слайд 14

LSP: Реализация Quad class Quad : public Rectangle { public: void

LSP: Реализация Quad

class Quad : public Rectangle
{
public:
void SetWidth(int w) {

w_ = w; h_ = w; }
void SetHeight(int w) { w_ = w; h_ = w; }
};

Семантика quad соблюдена

Слайд 15

Нарушение LSP void g(Rectangle *p) { p->SetHeight(5); p->SetWidth(4); assert(p->GetArea() == 20);

Нарушение LSP

void g(Rectangle *p)
{
p->SetHeight(5);
p->SetWidth(4);
assert(p->GetArea() == 20);
}

Ошибки проектирования иерархии
При

реализации Quad потребовалось сделать изменения в базовом Rectangle (+ virtual)
Семантика методов базового класса поменялась
Ранее разделенные методы стали зависимы
Quad не является Rectangle в данном контексте