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); } }