Функторы. Namespaces

Материал из SEWiki
Перейти к: навигация, поиск

Функторы

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 аргументов(это первый шаг)

Поиск Кенига.