SlideShare a Scribd company logo
1 of 48
Обобщенное программирование в C++
Как сделать свою жизнь проще через
страдания
Гомон Сергей, Regula (Siarhei.Homan@regula.by)
Обо мне
2
Siarhei.Homan@regula.by
Основные сферы интересов:
● Защита информации
● Сетевая разработка
● Обработка изображений
Содержание
Понятие обобщенного программирования
Правила вывода шаблонных типов C++
Основные определения и терминология
Примеры
Ссылки
3
Что такое обобщенное
программирование
4
Обобщенное программирование
5
Шаблоны C++ генерируют программы
6
Обобщенная программа
Обычные программы
Конкретные типы и
значения
STL значит STepanov and Lee
Александр Степанов, автор STL
7
Базовый синтаксис
8
template<typename ArrayType, int ArraySize>
class FixedSizeArray
{
public:
FixedSizeArray() { std::fill(std::begin(arr_), std::end(arr_), 0); }
ArrayType& at(int idx) { return arr_[idx]; }
const ArrayType& at(int idx) const { return arr_[idx]; }
private:
ArrayType arr_[ArraySize];
};
FixedSizeArray<int, 5> array;
array.at(0) = 5;
int first_elem = array.at(0);
Шаблоны в Си
9
#define VECTOR(ArrayType, ArraySize, TypeName) 
class FixedSizeArray##TypeName { 
public: 
FixedSizeArray##TypeName() { std::fill(std::begin(arr_), std::end(arr_), 0); } 
ArrayType& at(int idx) { return arr_[idx]; } 
const ArrayType& at(int idx) const { return arr_[idx]; } 
private: 
ArrayType arr_[ArraySize]; 
};
VECTOR(int, 5, Int5)
FixedSizeArrayInt5 array;
array.at(0) = 5;
int first_elem = array.at(0);
Шаблоны в других языкаx
10
C++
Правила вывода типов
11
Вывод типов
12
template<typename T>
void f(ParamType param);
f(expr);
// Example:
template<typename T>
void f(const T& param);
int x = 0;
f(x); // T is int, ParamType is const int&
PyramType - не ссылка и не указатель
13
template<typename T>
void f(T param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T is int, ParamType is int
f(cx); // T is int, ParamType is int
f(rx); // T is int, ParamType is int
ParamType - ссылка
14
template<typename T>
void f(T& param); // param is a reference
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T is int, ParamType is int&
f(cx); // T is const int, ParamType is const int&
f(rx); // T is const int, ParamType is const int&
ParamType - константная ссылка
15
template<typename T>
void f(const T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T is int, ParamType is const int&
f(cx); // T is int, ParamType is const int&
f(rx); // T is int, ParamType is const int&
ParamType - указатель
16
template<typename T>
void f(T* param);
int x = 27;
const int *px = &x;
f(&x); // T is int, ParamType is int*
f(px); // T is const int, ParamType const int*
ParamType - универсальная ссылка
17
template<typename T>
void f(T&& param); // param is now a universal reference
int x = 27;
const int cx = x;
const int& rx = x;
// l-value examples
f(x); // T is int&, ParamType is int&
f(cx); // T is const int&, ParamType is const int&
f(rx); // T is const int&, ParamType is const int&
// r-value example
f(27); // T is int, ParamType is int&&
ParamType - массив
18
const char name[] = "J. P. Briggs";
template<typename T>
void f(T param);
f(name); // T is const char*, ParamType is const char*
template<typename T>
void f(T& param);
f(name); // T is const char [13], ParamType is const char (&)[13]
// Compile time array size
template<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept {
return N;
}
ParamType - функция
19
void someFunc(int, double);
template<typename T>
void f1(T param);
template<typename T>
void f2(T& param);
f1(someFunc); // T is void (*)(int, double), ParamType is void (*)(int, double)
f2(someFunc); // T is void (&)(int, double), ParamType is void (&)(int, double)
20
Основные определения
21
22
Шаблонная функция
(function template)
Функция шаблона
(template function)
Инстанцирование
template class std::array<int, 5>; // Explicit instantiation
std::array<int, 5> arr1; // Explicit instantiation used
std::array<int, 6> arr2; // Implicit instantiation used
Концепты
23
template<typename T>
class HasClone {
public:
static void Constraints() {
typedef T* (T::*CloneFunc)() const;
CloneFunc hasCloneFunc = &T::Clone;
}
HasClone() { void (*p)() = Constraints; }
};
template<typename T>
class C : HasClone<T> {
// ...
};
Специализация
24
template<>
class A<int> { /*...*/ }; // Specialization
template<typename S, typename U>
class A<std::map<S, U>> { /*...*/ }; // partial specialization
Характеристики (traits)
25
template <class T, T val>
struct integral_constant {
typedef integral_constant<T, val> type;
typedef T value_type;
static const T value = val;
};
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
Характеристики (traits) (2)
26
template <typename T> struct is_void : public false_type {};
template <> struct is_void<void> : public true_type {};
std::cout << is_void<void>::value << std::endl; // true
std::cout << is_void<int >::value << std::endl; // false
template <typename T> struct is_pointer : public false_type{};
template <typename T> struct is_pointer<T*> : public true_type{};
std::cout << is_pointer<int*>::value << std::endl; // true
std::cout << is_pointer<int >::value << std::endl; // false
Variadic Templates
Разворачивание шаблоно! может иметь место только в определенных
контекстах:
Список аргументов функции: f(&args...);
Список аргументов шаблона: container<A,B,C...> t1;
Список параметров функции: template<typename ...Ts> void f(Ts...) {}
Список параметров шаблона: template<T... Values>
Базовые классы и список инициализации класса: class X : public Mixins...
Список инициализации: int res[sizeof...(args) + 2] = {1,args...,2}; 27
Примеры
28
Факториал времени компиляции
29
template<int n>
struct Factorial {
static const int f = Factorial<n-1>::f * n;
};
template<>
struct Factorial<0> {
static const int f = 1;
};
std::cout << Factorial<5>::f << std::endl; // 120
Обфрускация строк времени компиляции
30
template<std::size_t SIZE>
struct hiddenString {
short s[SIZE];
constexpr hiddenString(): s{0} {}
std::string decode() const {
std::string rv;
rv.reserve(SIZE + 1);
std::transform(s, s + SIZE - 1,
std::back_inserter(rv),
[](auto ch) { return ch - 1; });
return rv;
}
};
Обфрускация строк времени компиляции (2)
31
template<typename T, size_t N>
constexpr std::size_t sizeCalculate(const T(&)[N]) { return N; }
template<std::size_t SIZE>
constexpr auto encoder(const char str[SIZE]) {
hiddenString<SIZE> encoded;
for(std::size_t i = 0; i < SIZE - 1; i++)
encoded.s[i] = str[i] + 1;
encoded.s[SIZE - 1] = 0;
return encoded;
}
#define CRYPTEDSTRING(name, x) 
constexpr auto name = encoder<sizeCalculate(x)>(x)
Обфрускация строк времени компиляции (3)
32
CRYPTEDSTRING(str, "Big big secret!");
std::cout << str.decode() << std::endl;
Tuple
33
template<typename... Args> struct tuple;
template<typename Head, typename... Tail>
struct tuple<Head, Tail...> : tuple<Tail...> {
tuple(Head h, Tail... tail) : tuple<Tail...>(tail...), head_(h) {}
typedef tuple<Tail...> base_type;
typedef Head value_type;
base_type& base = static_cast<base_type&>(*this);
Head head_;
};
template<> struct tuple<> {};
tuple<int, double, int> t(12, 2.34, 89);
std::cout << t.head_ << " " << t.base.head_ << " " << t.base.base.head_ <<
std::endl;
Функции для Tuple
34
template<int I, typename Head, typename... Args>
struct getter {
typedef typename getter<I-1, Args...>::return_type return_type;
static return_type get(tuple<Head, Args...> t) {
return getter<I-1, Args...>::get(t);
}
};
template<typename Head, typename... Args>
struct getter<0, Head, Args...> {
typedef typename tuple<Head, Args...>::value_type return_type;
static return_type get(tuple<Head, Args...> t) {
return t.head_;
}
};
Функции для Tuple (2)
35
template<int I, typename Head, typename... Args>
typename getter<I, Head, Args...>::return_type get(tuple<Head, Args...> t) {
return getter<I, Head, Args...>::get(t);
}
test::tuple<int, double, int> t(12, 2.34, 89);
std::cout << get<0>(t) << " " << get<1>(t) << “ “ << get<2>(t) << std::endl;
Применение функции к Tuple
36
template<typename F, typename Tuple, int... N>
auto call(F f, Tuple &&t) {
return f(std::get<N>(t)...);
}
int sum(int a, int b, int c) {
return a + b + c;
}
td::tuple<int, int, int> args(1, 2, 3);
call<int(&)(int,int,int), std::tuple<int,int,int>&, 0, 1, 2>(sum, args);
Применение функции к Tuple (2)
37
template<typename F, typename Tuple, bool Enough, int TotalArgs, int... N>
struct call_impl {
auto static call(F f, Tuple&& t) {
return call_impl<F, Tuple, TotalArgs == 1 + sizeof...(N),
TotalArgs, N..., sizeof...(N)
>::call(f, std::forward<Tuple>(t));
}
};
Применение функции к Tuple (3)
38
template<typename F, typename Tuple, int TotalArgs, int... N>
struct call_impl<F, Tuple, true, TotalArgs, N...> {
auto static call(F f, Tuple&& t) {
return f(std::get<N>(std::forward<Tuple>(t))...);
}
};
Применение функции к Tuple (4)
39
template<typename F, typename Tuple>
auto call(F f, Tuple&& t) {
typedef typename std::decay<Tuple>::type type;
return call_impl<F, Tuple, 0 == std::tuple_size<type>::value,
std::tuple_size<type>::value
>::call(f, std::forward<Tuple>(t));
}
call(sum, args);
PRC на основе boost.asio и boost.serialization
40
https://github.com/gomons/CppRpcLight
Service.h
41
//RPC_DEFINE(funcname, returnType , args...);
RPC_DEFINE(sum , int , int, int);
RPC_DEFINE(echo , std::string, std::string);
Service.cpp (Выполняется на сервере)
42
RPC_DECLARE(sum, int, int a, int b) {
return a + b;
}
RPC_DECLARE(echo, std::string, std::string str) {
return str;
}
Запуск сервера
43
boost::asio::io_service io_service;
RpcServer prc_server(io_service);
io_service.run();
Запуск клиента
44
boost::asio::io_service io_service;
cpp_rpc_light::ClientConnection client_сonnection(io_service);
std::thread thread([&io_service]() {
io_service.run();
});
client_сonnection.WaitForConnect();
Вызов удаленной функции
45
auto sum_res = sum(client_сonnection, 5, 6);
auto sum_future = sum_async(client_сonnection, 5, 6);
auto sum_res2 = sum_future.get();
auto echo_res = echo(client_сonnection, std::string("Ping!"));
auto echo_future = echo_async(client_сonnection, std::string("Ping!"));
auto echo_res2 = echo_future.get();
Немного о страданиях
Разные компиляторы поддерживают немного разный синтаксис
Трудно найти проблему по диагностическому сообщению
Только новые компиляторы
Сложно писать, поддерживать, разбираться
Долгая компиляция, большой размер бинарника
Код шаблонов должне находиться в заголовочном файле
46
Спасибо за внимание!
47
Ссылки
Scott Meyers - Effective Modern C++
Stroustrup - A Tour of C++ - 2013
Sutter, Alexandrescu - C++ Coding Standart
https://m.habrahabr.ru/post/54762/
https://habrahabr.ru/post/166849/
https://habrahabr.ru/post/228031/
https://habrahabr.ru/post/245719/
48

More Related Content

What's hot

Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Platonov Sergey
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Dima Dzuba
 

What's hot (20)

Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
 
Haskell
HaskellHaskell
Haskell
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11Дмитрий Прокопцев — R-ссылки в С++11
Дмитрий Прокопцев — R-ссылки в С++11
 
Python
PythonPython
Python
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
 
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
Объектно-Ориентированное Программирование на C++, Лекции  3 и 4 Объектно-Ориентированное Программирование на C++, Лекции  3 и 4
Объектно-Ориентированное Программирование на C++, Лекции 3 и 4
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 
Concepts lite
Concepts liteConcepts lite
Concepts lite
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
 

Viewers also liked

Разработка и тестирование интернета вещей. Тренды индустрии
Разработка и тестирование интернета вещей. Тренды индустрииРазработка и тестирование интернета вещей. Тренды индустрии
Разработка и тестирование интернета вещей. Тренды индустрии
corehard_by
 

Viewers also liked (12)

Теория и практика написания безопасного кода на C++
Теория и практика написания безопасного кода на C++Теория и практика написания безопасного кода на C++
Теория и практика написания безопасного кода на C++
 
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtДенис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
 
Хитрости мультипоточности
Хитрости мультипоточностиХитрости мультипоточности
Хитрости мультипоточности
 
упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)
упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)
упрощаем переход от Json к c++ структурам и обратно (николай гродзицкий)
 
Разработка и тестирование интернета вещей. Тренды индустрии
Разработка и тестирование интернета вещей. Тренды индустрииРазработка и тестирование интернета вещей. Тренды индустрии
Разработка и тестирование интернета вещей. Тренды индустрии
 
о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++о некоторых вопросах бинарной совместимости в C++
о некоторых вопросах бинарной совместимости в C++
 
Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projects
 

Similar to Обобщенное программирование в C++ или как сделать свою жизнь проще через страдания

Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
Andrey Karpov
 
6.3 Специализация шаблонов
6.3 Специализация шаблонов6.3 Специализация шаблонов
6.3 Специализация шаблонов
DEVTYPE
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
Technopark
 

Similar to Обобщенное программирование в C++ или как сделать свою жизнь проще через страдания (20)

стандартная библиотека с++: введение
стандартная библиотека с++: введениестандартная библиотека с++: введение
стандартная библиотека с++: введение
 
C language. Introduction
C language. IntroductionC language. Introduction
C language. Introduction
 
6.2 Шаблоны функций
6.2 Шаблоны функций6.2 Шаблоны функций
6.2 Шаблоны функций
 
Document
DocumentDocument
Document
 
Tricky Java Generics
Tricky Java GenericsTricky Java Generics
Tricky Java Generics
 
Rgsu04
Rgsu04Rgsu04
Rgsu04
 
Rgsu04
Rgsu04Rgsu04
Rgsu04
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
6.4 Ещё о шаблонах
6.4 Ещё о шаблонах6.4 Ещё о шаблонах
6.4 Ещё о шаблонах
 
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++.   Р...
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...
 
PascalABC.NET 2015-2016
PascalABC.NET 2015-2016PascalABC.NET 2015-2016
PascalABC.NET 2015-2016
 
Array Work C
Array Work CArray Work C
Array Work C
 
Опыт разработки статического анализатора кода
Опыт разработки статического анализатора кодаОпыт разработки статического анализатора кода
Опыт разработки статического анализатора кода
 
6.3 Специализация шаблонов
6.3 Специализация шаблонов6.3 Специализация шаблонов
6.3 Специализация шаблонов
 
DSLs in Lisp and Clojure
DSLs in Lisp and ClojureDSLs in Lisp and Clojure
DSLs in Lisp and Clojure
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8. Объектно-ориентированное программирование. Лекция 7 и 8.
Объектно-ориентированное программирование. Лекция 7 и 8.
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
основы Java переменные, циклы
основы Java   переменные, циклыосновы Java   переменные, циклы
основы Java переменные, циклы
 
Algo 00
Algo 00Algo 00
Algo 00
 

More from corehard_by

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 

Обобщенное программирование в C++ или как сделать свою жизнь проще через страдания

  • 1. Обобщенное программирование в C++ Как сделать свою жизнь проще через страдания Гомон Сергей, Regula (Siarhei.Homan@regula.by)
  • 2. Обо мне 2 Siarhei.Homan@regula.by Основные сферы интересов: ● Защита информации ● Сетевая разработка ● Обработка изображений
  • 3. Содержание Понятие обобщенного программирования Правила вывода шаблонных типов C++ Основные определения и терминология Примеры Ссылки 3
  • 6. Шаблоны C++ генерируют программы 6 Обобщенная программа Обычные программы Конкретные типы и значения
  • 7. STL значит STepanov and Lee Александр Степанов, автор STL 7
  • 8. Базовый синтаксис 8 template<typename ArrayType, int ArraySize> class FixedSizeArray { public: FixedSizeArray() { std::fill(std::begin(arr_), std::end(arr_), 0); } ArrayType& at(int idx) { return arr_[idx]; } const ArrayType& at(int idx) const { return arr_[idx]; } private: ArrayType arr_[ArraySize]; }; FixedSizeArray<int, 5> array; array.at(0) = 5; int first_elem = array.at(0);
  • 9. Шаблоны в Си 9 #define VECTOR(ArrayType, ArraySize, TypeName) class FixedSizeArray##TypeName { public: FixedSizeArray##TypeName() { std::fill(std::begin(arr_), std::end(arr_), 0); } ArrayType& at(int idx) { return arr_[idx]; } const ArrayType& at(int idx) const { return arr_[idx]; } private: ArrayType arr_[ArraySize]; }; VECTOR(int, 5, Int5) FixedSizeArrayInt5 array; array.at(0) = 5; int first_elem = array.at(0);
  • 10. Шаблоны в других языкаx 10 C++
  • 12. Вывод типов 12 template<typename T> void f(ParamType param); f(expr); // Example: template<typename T> void f(const T& param); int x = 0; f(x); // T is int, ParamType is const int&
  • 13. PyramType - не ссылка и не указатель 13 template<typename T> void f(T param); int x = 27; const int cx = x; const int& rx = x; f(x); // T is int, ParamType is int f(cx); // T is int, ParamType is int f(rx); // T is int, ParamType is int
  • 14. ParamType - ссылка 14 template<typename T> void f(T& param); // param is a reference int x = 27; const int cx = x; const int& rx = x; f(x); // T is int, ParamType is int& f(cx); // T is const int, ParamType is const int& f(rx); // T is const int, ParamType is const int&
  • 15. ParamType - константная ссылка 15 template<typename T> void f(const T& param); int x = 27; const int cx = x; const int& rx = x; f(x); // T is int, ParamType is const int& f(cx); // T is int, ParamType is const int& f(rx); // T is int, ParamType is const int&
  • 16. ParamType - указатель 16 template<typename T> void f(T* param); int x = 27; const int *px = &x; f(&x); // T is int, ParamType is int* f(px); // T is const int, ParamType const int*
  • 17. ParamType - универсальная ссылка 17 template<typename T> void f(T&& param); // param is now a universal reference int x = 27; const int cx = x; const int& rx = x; // l-value examples f(x); // T is int&, ParamType is int& f(cx); // T is const int&, ParamType is const int& f(rx); // T is const int&, ParamType is const int& // r-value example f(27); // T is int, ParamType is int&&
  • 18. ParamType - массив 18 const char name[] = "J. P. Briggs"; template<typename T> void f(T param); f(name); // T is const char*, ParamType is const char* template<typename T> void f(T& param); f(name); // T is const char [13], ParamType is const char (&)[13] // Compile time array size template<typename T, std::size_t N> constexpr std::size_t arraySize(T (&)[N]) noexcept { return N; }
  • 19. ParamType - функция 19 void someFunc(int, double); template<typename T> void f1(T param); template<typename T> void f2(T& param); f1(someFunc); // T is void (*)(int, double), ParamType is void (*)(int, double) f2(someFunc); // T is void (&)(int, double), ParamType is void (&)(int, double)
  • 20. 20
  • 22. 22 Шаблонная функция (function template) Функция шаблона (template function) Инстанцирование template class std::array<int, 5>; // Explicit instantiation std::array<int, 5> arr1; // Explicit instantiation used std::array<int, 6> arr2; // Implicit instantiation used
  • 23. Концепты 23 template<typename T> class HasClone { public: static void Constraints() { typedef T* (T::*CloneFunc)() const; CloneFunc hasCloneFunc = &T::Clone; } HasClone() { void (*p)() = Constraints; } }; template<typename T> class C : HasClone<T> { // ... };
  • 24. Специализация 24 template<> class A<int> { /*...*/ }; // Specialization template<typename S, typename U> class A<std::map<S, U>> { /*...*/ }; // partial specialization
  • 25. Характеристики (traits) 25 template <class T, T val> struct integral_constant { typedef integral_constant<T, val> type; typedef T value_type; static const T value = val; }; typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type;
  • 26. Характеристики (traits) (2) 26 template <typename T> struct is_void : public false_type {}; template <> struct is_void<void> : public true_type {}; std::cout << is_void<void>::value << std::endl; // true std::cout << is_void<int >::value << std::endl; // false template <typename T> struct is_pointer : public false_type{}; template <typename T> struct is_pointer<T*> : public true_type{}; std::cout << is_pointer<int*>::value << std::endl; // true std::cout << is_pointer<int >::value << std::endl; // false
  • 27. Variadic Templates Разворачивание шаблоно! может иметь место только в определенных контекстах: Список аргументов функции: f(&args...); Список аргументов шаблона: container<A,B,C...> t1; Список параметров функции: template<typename ...Ts> void f(Ts...) {} Список параметров шаблона: template<T... Values> Базовые классы и список инициализации класса: class X : public Mixins... Список инициализации: int res[sizeof...(args) + 2] = {1,args...,2}; 27
  • 29. Факториал времени компиляции 29 template<int n> struct Factorial { static const int f = Factorial<n-1>::f * n; }; template<> struct Factorial<0> { static const int f = 1; }; std::cout << Factorial<5>::f << std::endl; // 120
  • 30. Обфрускация строк времени компиляции 30 template<std::size_t SIZE> struct hiddenString { short s[SIZE]; constexpr hiddenString(): s{0} {} std::string decode() const { std::string rv; rv.reserve(SIZE + 1); std::transform(s, s + SIZE - 1, std::back_inserter(rv), [](auto ch) { return ch - 1; }); return rv; } };
  • 31. Обфрускация строк времени компиляции (2) 31 template<typename T, size_t N> constexpr std::size_t sizeCalculate(const T(&)[N]) { return N; } template<std::size_t SIZE> constexpr auto encoder(const char str[SIZE]) { hiddenString<SIZE> encoded; for(std::size_t i = 0; i < SIZE - 1; i++) encoded.s[i] = str[i] + 1; encoded.s[SIZE - 1] = 0; return encoded; } #define CRYPTEDSTRING(name, x) constexpr auto name = encoder<sizeCalculate(x)>(x)
  • 32. Обфрускация строк времени компиляции (3) 32 CRYPTEDSTRING(str, "Big big secret!"); std::cout << str.decode() << std::endl;
  • 33. Tuple 33 template<typename... Args> struct tuple; template<typename Head, typename... Tail> struct tuple<Head, Tail...> : tuple<Tail...> { tuple(Head h, Tail... tail) : tuple<Tail...>(tail...), head_(h) {} typedef tuple<Tail...> base_type; typedef Head value_type; base_type& base = static_cast<base_type&>(*this); Head head_; }; template<> struct tuple<> {}; tuple<int, double, int> t(12, 2.34, 89); std::cout << t.head_ << " " << t.base.head_ << " " << t.base.base.head_ << std::endl;
  • 34. Функции для Tuple 34 template<int I, typename Head, typename... Args> struct getter { typedef typename getter<I-1, Args...>::return_type return_type; static return_type get(tuple<Head, Args...> t) { return getter<I-1, Args...>::get(t); } }; template<typename Head, typename... Args> struct getter<0, Head, Args...> { typedef typename tuple<Head, Args...>::value_type return_type; static return_type get(tuple<Head, Args...> t) { return t.head_; } };
  • 35. Функции для Tuple (2) 35 template<int I, typename Head, typename... Args> typename getter<I, Head, Args...>::return_type get(tuple<Head, Args...> t) { return getter<I, Head, Args...>::get(t); } test::tuple<int, double, int> t(12, 2.34, 89); std::cout << get<0>(t) << " " << get<1>(t) << “ “ << get<2>(t) << std::endl;
  • 36. Применение функции к Tuple 36 template<typename F, typename Tuple, int... N> auto call(F f, Tuple &&t) { return f(std::get<N>(t)...); } int sum(int a, int b, int c) { return a + b + c; } td::tuple<int, int, int> args(1, 2, 3); call<int(&)(int,int,int), std::tuple<int,int,int>&, 0, 1, 2>(sum, args);
  • 37. Применение функции к Tuple (2) 37 template<typename F, typename Tuple, bool Enough, int TotalArgs, int... N> struct call_impl { auto static call(F f, Tuple&& t) { return call_impl<F, Tuple, TotalArgs == 1 + sizeof...(N), TotalArgs, N..., sizeof...(N) >::call(f, std::forward<Tuple>(t)); } };
  • 38. Применение функции к Tuple (3) 38 template<typename F, typename Tuple, int TotalArgs, int... N> struct call_impl<F, Tuple, true, TotalArgs, N...> { auto static call(F f, Tuple&& t) { return f(std::get<N>(std::forward<Tuple>(t))...); } };
  • 39. Применение функции к Tuple (4) 39 template<typename F, typename Tuple> auto call(F f, Tuple&& t) { typedef typename std::decay<Tuple>::type type; return call_impl<F, Tuple, 0 == std::tuple_size<type>::value, std::tuple_size<type>::value >::call(f, std::forward<Tuple>(t)); } call(sum, args);
  • 40. PRC на основе boost.asio и boost.serialization 40 https://github.com/gomons/CppRpcLight
  • 41. Service.h 41 //RPC_DEFINE(funcname, returnType , args...); RPC_DEFINE(sum , int , int, int); RPC_DEFINE(echo , std::string, std::string);
  • 42. Service.cpp (Выполняется на сервере) 42 RPC_DECLARE(sum, int, int a, int b) { return a + b; } RPC_DECLARE(echo, std::string, std::string str) { return str; }
  • 44. Запуск клиента 44 boost::asio::io_service io_service; cpp_rpc_light::ClientConnection client_сonnection(io_service); std::thread thread([&io_service]() { io_service.run(); }); client_сonnection.WaitForConnect();
  • 45. Вызов удаленной функции 45 auto sum_res = sum(client_сonnection, 5, 6); auto sum_future = sum_async(client_сonnection, 5, 6); auto sum_res2 = sum_future.get(); auto echo_res = echo(client_сonnection, std::string("Ping!")); auto echo_future = echo_async(client_сonnection, std::string("Ping!")); auto echo_res2 = echo_future.get();
  • 46. Немного о страданиях Разные компиляторы поддерживают немного разный синтаксис Трудно найти проблему по диагностическому сообщению Только новые компиляторы Сложно писать, поддерживать, разбираться Долгая компиляция, большой размер бинарника Код шаблонов должне находиться в заголовочном файле 46
  • 48. Ссылки Scott Meyers - Effective Modern C++ Stroustrup - A Tour of C++ - 2013 Sutter, Alexandrescu - C++ Coding Standart https://m.habrahabr.ru/post/54762/ https://habrahabr.ru/post/166849/ https://habrahabr.ru/post/228031/ https://habrahabr.ru/post/245719/ 48

Editor's Notes

  1. Обобщенное программирование - это подход, при котором при написании алгоритмов используются не конкретные типы данных, а некоторые их абстрактные описания. Как следствие, алгоритм может работать с любыми типами данных, которые поддерживают данное описание. В результате вместо программы у нас получается шаблон программы, в который можно подставлять разные типы. В C++ основным средством поддержания обобщенного программирования являются шаблоны или темплейты.
  2. Программа на C++, которая содержит шаблоны - это уже не просто программа, а метапрограмма. Используя шаблонный код и конкретные значения параметров этого шаблонного кода, компилятор генерирует программу, которая потом идет на компиляцию.
  3. Превосходным примером эффективности и красоты обобщенного программирования является библиотека STL, написанная Александром Степановым при поддержке Меган Ли. Эти люди стоят у истоков обобщенного программирования в C++. В 1992 году они занимались исследованиями в области обобщенного программирования. Вопрос состоял в том, чтобы проверить, можно ли писать программы максимально обобщенным способом, чтобы при этом они не теряли своей эффективности. Оказалось, что это возможно. Также стоит отметить работы Андрея Александреску. В его книге можно найти очень интересный подход к обобщенному программированию. Его библиотека Loki - это своеобразная мета-библиотека для C++, которая позволяет сгенерировать библиотеку для конкретных нужд за счет настраивания через специальные классы-стратегии.
  4. В C++ шаблоном может быть класс либо функция. Базовый синтаксис шаблонов довольно прост. Перед классом или функцией пишется ключевое слово template, после которого в угловых скобках перечисляются аргументы шаблона. В качестве аргументов шаблона могут выступать типы, значения, а также другие шаблоны. В определении класса или функции в качестве типов и констант можно использовать параметры шаблона. На слайде приведет простой класс статического массива фиксированного размера. Преимуществом данного подхода по сравнению с обычными статическими массивами является то, что в методах доступа к элементам массива можно добавить проверки, чтобы не допустить выход за границы массива. В стандартной библиотеке уже есть такой класс, это std::array.
  5. До появления шаблонов, в C++ был механизм метапрограммирования - это препроцессор Си. На слайде показан пример, аналогичный рассмотренному ранее, но без использования шаблонов. К недостаткам данного метода можно отнести то, что каждый новый тип нужно объявлять вручную. Но основным недостатком данного подхода является обильное использование макросов, что делает программы слишком сложными для отладки.
  6. В разных языках обобщенное программирование поддерживается по-разному и выполняет разные цели. Например, в Java есть дженерики, которые работают через механизм type erasure и фактически используются только для усиления типизации языка. Обобщенные контейнеры в Java были и до появления дженериков, и работали через общий базовый класс. Похожая ситуация обстоит и с C. В этих языка используется похожий с C++ синтаксис, но способ работы данного механизма в этих языках абсолютно отличаются. В C++ шаблоны - это средство генерации кода. По описанию программы компилятор генерирует нужный нам код. Как следствие получается программа, которая не требует дополнительных ресурсов во время выполнения. В Java и C# это не так, там дженерики - это механизм времени выполнения, который не позволяет генерировать новый код.
  7. Без понимани правил вывода типов C++, практически невозможно писать сложных программ с использованием шаблонов. На слайде представлены элементы, которые будут использоваться для объяснения правил вывода типов. В ходе процедуры вывода типов вычисляется значение 2-х типов: для T и для ParamType. Как правило, эти типы отличаются. ParamType часто может иметь квалификаторы const, может быть типом ссылки или указателя. Тип, который выводится для T, зависит от того, какие к квалификаторы используются для типа ParamType. Условно можно выделить 3 случая: ParamType - ссылка или указатель ParamType - универсальная ссылка ParamType - не ссылка и не указатель
  8. В данном случае при выводе типа T, квалификаторы const, volotile агрумента, а также его ссылочность игнорирутся. T и PatamType имеют одинаковый тип.
  9. Рассмотрим случай, когда ParamType - это ссылка или указатель. В данном случае правила вывода типа работают следующим образом: если тип аргумента - ссылка, то она игнорируется. Тут мы видим, что если в качестве аргумента шаблонной функции передается константынй тип, то константность становится частью шаблонного типа T. В случае передачи в функцию ссылочного типа rx, тип T игнорирует ссылочность.
  10. Если мы будем передавать в функцию значение по константной ссылке, то константность перестанет быть частью типа T. В остальном все остантеся, как прежде.
  11. Если ParamType является указателем, то все происходит с точностью, как и с ссылками. Параметр T игнорирует то, что тип аргумента функции - ссылка. Далее вывод типов происходит по тем же правилам, как рассказывалось раньше.
  12. С C++11 появились rvalue-reference. При выводе типов шаблона для них работают отдельные правила. Типы выводятся по-разному в зависимости от того, передаем мы в функцию l-value или r-value. При передаче l-value, T и ParamType имеют одинаковые типы, при передаче r-value, T игнорирует ссылочность типа, а ParamType имеет r-value тип.
  13. Для массивов и функций при выводе типов работают отдельные правила. Они одинаковые для массивов и функций. Особенностью передачи массивов по значению является то, что при этом происходит передача указателя на первый элемент массива, т. е. тип массива теряется. Однако как массив, так и функцию можно передавать по ссылке, тогда их типы сохраняются. Это дает возможность, например, определять размер массива во время компиляции.
  14. Как упоминалось выше, тут работаю все те же самые правила, что и с массивами.
  15. В
  16. В мире C++ принято различать шаблонную функцию и функцию шаблона. Под шаблонной функцией обычно понимают то, что пишется после ключивого слово template. Функция шаблоно - это конкретный экземпляр шаблонной функции (шаблоны в C++ - средство генерации кода). Очень часто эти понятия использут взаимозаменяемо. Шаблонный класс сам по себе не является типом, функцией или объектом. Чтобы сгенерировать код из шаблоноа, его нужно инстанцировать. Инстанцирование может быть явным и неявным. Неявное инстанцирование происходит в местах, где код ссылается на шаблон в контексте, где требуется его определение и при этом до этого не было произведено явное инстанцирование.
  17. Концепты (concepts) - требования и ограничения, накладываемые на параметры шаблона. C++ не поддерживает концептов. Но в некотором виде это можно компенсировать различными приемами программирования. На слайде представлен способ проверки наличия у шаблонного типа матода определенной сигнатуры: определенного возвращаемого типа и определенных значений параметров. Если шаблонный параметр не будет иметь функцию такой сигнатуры, произойдет ошибка компиляции.
  18. Специализация - это механизм, который позволяет предоставить реализацию шаблона для конкретного типа. Специализация может быть полной, а может быть частичной. Функции не поддерживают частичную специализацию, а классы - поддерживают. Частично специализированный шаблон - это новый шаблон, который может иметь свой список параметров.
  19. Характеристики - это метод обобщенного программирования, который позволяет принимать решения во время компиляции. Работа данного механизма основана на частичной специализации.
  20. Вариадики - мощнейший и долгожеланный механизм, который позволяет избавиться от огромнейшего количества хаков, которые раньше применялись для их имитации. Да, вариадики раньше применялись, на чаще всего для них были установдены ограничения, предусмотренные автором библиотеки. Например, в некоторых реализациях кортеджей максимальное количество элементов не могло превышать 10. 10 - это большое число для картеджа, и все же иногда его не хватало. В приходом вариадиков эти ограничения остались в прошлом. Вариадики позволяют писать программы времени компиляции в функциональном стили, где последовательность параметров разделяется на голову и хвост. Голова списка обрабатывается, а для хвоста списка вызывается рекурсивная обработка. Нужно понимать, что эта рекурсивная обработка выполняется компилятором, что может сильно замедлить время его работы, а также она имеет некоторые ограничения. Да, это не число 10, однако не стоит сильно увлекаться. Ложкой дегдя в этом всем является то, что вариадики могут раскрываться только в нескольких контекстах.
  21. Constexpr позволяет указать, какие вычисления должны выполняться во время компиляции. Такие выражения затем можно использовать в контекстах, где разрешается использовать только константы. Использование constexpr при объявлении объектов подразумевает, что они будут константными, а при исползовании для объявления функций, что они будут инлайниться. Однако при этом на constexpr выражения накладываются довольно жесткие ограничения. В частности, такие функции не должны быть вируальными, должны возрващать литеральный тип, в качестве аргументов принимают только литеральные типы. Constexpr выражения позволяют писать более крутые метапрограммы. Например, можно обфрусцировать строки во время компиляции. В данном случае мы объявляем функцию sizeCalculate, которая выполняется во время компиляции и преобразует строку, в данном случае добавляет к каждому симполу 1. Но с таким подходом есть, как минимум, 2 проблемы: далеко не все компиляторы это скомпилируют, а если и скомпилируют, то оптимизатор может убрать все вычисления времени компиляции и заменить строки константами, что сведет на нет наши старания.
  22. Теперь вернемся к практическому аспекту обобщенного программирования. Ранее упоминался такой тип, как картедж. В C++11 его реализация стала довольно понятной. Кортедже очень широко распространены в функциональном программировании. Далее мы увидим, что некоторые аспекты фукнционального программирования также применимы в C++. При работе с вариадиками, особое значение имеет рекурсия. Как правило, списко типов разделяется на голову и тело. Голова обрабатывается, а для тела рекурсивно вызывается функция. При это нужно не забыть определить окончание рекурсии, иначе программа не скомпилируется.
  23. В принцепе tuple готов к использованию. Однака данный вариант очень неудобен в использовании. Чтобы это исправить, обычно пишут функции доступа к элементам tuple.
  24. Большинство продемонстрированных примеров были взяты из интернета. Это был готовый и отлаженный код, в котором были предусмотрены многие нюансы. Однако если приходится написать что-то новое, то, как правило, это становится настоящей головоломкой. И все бы ничего, но компилятор, который должен нам помогать, часто делает нашу жизнь невыносимой. Синтаксис шаблонов достаточно трудный, и разные компиляторы реализуют его со своими особенностями, некоторые из которых сложились исторически. Например, Visual Studio позволят скомпилировать код, который является неправильным по стандарту, что приводит к тому, что он не компилируется на GCC. При этом clang, при работе под Windows, пытается воспроизвести все послабления стандарта Visual Studio, но делает это не до конца. При этом диагностические сообщения выглядят так, что в них страшно смотреть. К сожалению, большинство проектов использует C++98, в котором возможности обобщенного программирования сильно ограничены или не такие удобные, как в C++11. Качественной шаблонной библиотекой очень удобно пользоваться, но нужно быть настоящим гуру, чтобы ее написать. Разбираться в программах с обильным использованием шаблонов тоже очень тяжело. Поэтому перед тем, как начинать активно везде использовать шаблоны, нужно провести тчательное исследование, на каких платформах и с какими людьми придется в будущем работать. Не смотря на то, что шаблоны - очень мощный механизм, им очень легко начать злоупотреблять. Поэтому при их использовании всегда нужно иметь в виду, что вы можете сделать жизнь других разработчиков невыносимой.