Skip to content

Latest commit

 

History

History
176 lines (161 loc) · 28.2 KB

Lecture 05.md

File metadata and controls

176 lines (161 loc) · 28.2 KB


Фичи?

Auto

std::vector<std::string> v;

for(std::vector<std::string>::iterator i = v.begin(); i != v.end(); i++) {} for(auto i = v.begin(); i != v.end(); i++) {}

auto выводится как шаблоны

auto a = f();
template <typename T>
void b(T);

auto& a = f(); template <typename T> void b(T&);

Чтобы не дублировать типы можно typedef'ать

typedef std::vector<std::string> strings;

Анонимные функции

template <typename It, typename Comp>
void sort(It first, It last, Comp comp) {
	...
	comp(..., ...);
	...
}

bool abs_less(int a, int b) { return abs(a) < abs(b); }

struct abs_less1 { bool operator()(int a, int b) const { return abs(a) < abs(b); } };

sort(v,begin(), v.end(), abs_less/abs_less1/std::less<int>);

Начиная с c++11 появились анонимные функции (лямбды) - это по сути функциональные объекты, которые за нас сгенерит компилятор

[](int a, int b) {
	return abs(a) < abs(b);
};

В [] указывается, что лямбда должна захватывать из контекста
Пусть мы ходим сравнивать по модулю

struct mod_less {
	mod_less(int n) : n(n) {}
	bool operator()(int a, int b) const {
		return a % n < b % n;
	}
	int n;
};

int k; sort(v,begin(), v.end(), mod_less(k));

Т.е нужны еще какие-то локальные данные. Тогда лямбда выглядит так:

[k](int a, int b) {
	return a % k, b % k;
}
Что можно Какой эффект
[a, b, c] Берутся следующие переменные по значению
[&d, &e, &f] Берутся по ссылке
[=, &d, &e, &f] Все по значению, а какие-то конкретные по ссылке
[&, a, b, c] Все по ссылке, а какие-то конкретные по значению
[this] this - объемлющего чувака

В следующем примере тип не может быть выведен тип, поскольку тип выводится по первому return, а для остальных проверяет, что он совпадает ( для лямбд работает так же)

auto fractional (int a) {
	if(a != 0) {
		return fractional(a - 1);
	} else {
		return 1;
	}
}

Иногда в лямбдах хочется указать тип возвращаемого значения

[]();
[]() -> bool //Возвращает bool

Иногда хочется, чтобы лямбда была не const (operator() не const)

[]() mutable -> bool;

А еще так можно сделать

auto f = [](int a) {};

И так, тогда это будет шаблонный функциональный объект

[](auto a, auto b) {
	return abs(a) < abs(b);
};

Что делать если хочется что-то такое?

auto cmp;
if (flag) {
	cmp = [](int a, int b) {return a < b;};
} else {
	cmp = [](int a, int b) {return b < a;};
}

Объявим cmp как

std::function<bool (int, int)> cmp;

Оффтоп

bool f(int, int);
bool g(int, int);
bool h(int, int);

sort(..., ..., &f); sort(..., ..., &g); sort(..., ..., &h);

struct F/G/H { bool operator()(int, int) {...} } sort(..., ..., F()); sort(..., ..., G()); sort(..., ..., H());

Второе работает быстрее (?), потому что новая структура - новый тип, новый сорт, можно инлайнить, а тип функций (в примере) одинаковый.

for(;;) {
	if(cmp == &f) {
		f(a, b);
	} else if(cmp == &g) {
		g(a, b);
	} else {
		cmp(a, b);
	}
}

Перепишется в if (cmp == &f) { for(;;) { f(a, b); } } else if (cmp == &g) { for(;;) { g(a, b); } } else { for(;;) { cmp(a, b); } }