Функторы. Namespaces — различия между версиями
(→Функторы) |
м (переименовал «Функторы, часть вторая. Иван Близнец. когда-то» в «Функторы. Namespaces») |
(нет различий)
|
Версия 12:22, 30 мая 2011
Функторы
find_if (p, q, Func); //ищет первый элемент, для которого функтор вернёт true
// Реализация функтора, который проверяет деление на 7.
struct Divby7 {
bool operator()(int i) const {
return i%7==0;
}
};
// Реализация функтора, который проверяет деление на любое число, которое будет передано в конструктор.
struct Divby {
Divby(int k) : k(k){}
bool operator()(int i) const {
return i%k==0;
}
const int k;
};
Можно писать find_if(p, q, Divby(5)), тогда в последовательности будет найден первый элемент, делящийся на 5.
stable_sort(p, qcomp_by_abs());
struct comp_by_abs {
bool operator()(int a, int b) const {
return abs(a) < abs(b);
}
};
Divby - унарный предикат (одноместный функтор). comp_by_abs - бинарный предикат.
transform(p,q,out, add(7));
struct add {
add(int k): k(k) {}
int operator()(int a) const {
return a+7;
}
};
Это уже непосредственно функтор (не предикат, поскольку возвращает не 0/1).
Стандартные функторы: minus, plus, divides, modulus, multiplies, logical_and, logical_or, logical_not. Бинарные предикаты(шаблонные): less, greater, less_equal, greater_equal, not_equal_to, equal_to.
find_if(p, q, bind1st(not_equal_to<int>(), 7)); // первый элемент, не равный 7
find_if(p, q, bind2nd(greater<int>(), 7)); // первый элемент, больший 7
Кроме bind1st, bind2nd есть еще not1, not2. Для того, чтобы пользовательские функторы можно было биндить, необходимо наследовать их от стандартных классов.
struct Divby : unary_function<int, bool> {
...
}
struct comp_by_abs : binary_function<int, int, bool>;
mem_fun - обёртка для member-функций (для указателей). mem_fun_ref - то же самое для ссылок. ptr_fun - обёртка для любой функции.
for_each(p, q, mem_fun_ref(vector<int>::clear));
not1(ptr_fun(is_add()));
Библиотека boost::bind:
boost::bind(vector<int>::resize,_1, 100,3);
Namespaces
int max(int, int) double max(double, double) namespace au { void f(){} }
Чтобы вызвать f, нужно написать au::f();
namespace noc { void g(){} } namespace au { void g(){} }
namespace не является чем-то целостным
namespace Ru{ namespace Spb{ namespace au{ int f(); } } namespave msk{} }
Ru::spb::au::f();
Для обращения к функции из глобального namespace нужно ::f();
Если в msk, будет еще Ru, то чтобы ***** из msk надо будет писать не Ru::spb, а ::Ru::spb. (коллизия двух Ru)
Поиск --ищет имя в текущем namespace --если не нашли переходим выше, если нашли запускаем перегрузку
namespace Ru { определно g(a,b) namespace spb { определено g(a) namesapce spbtele { вызываем g(a,b) } } namespace msk{} }
В предыдущем примере поиск остановиться в spb. Поскольку там тоде есть g. Поиск ищет только имя!
Чтобы избежать такое, надо в spb записать
using ::Ru::g;
%часть текста которую сложно расшифровать
НЕ НАДО=НЕЛЬЗЯ писать using namespave std;
Безымянный namespace
namespace {}
появиться уникальный namespace для каждого .cpp файла. Это позвляет создавать меленькие структуры не боясь перекрытия имен.
namespace a=ru::spb::au
И тогда можно будет писать a::f();.
ADL=argument dependent look up
namespace g { strcut complex{}; complex operator+(); } g::a+b %написано что-то непонятное а=g::operator+(a,b)
Поиск имен ***** там где мы находимся, а также и в namespace аргументов(это первый шаг)
Поиск Кенига.