Функторы. Namespaces — различия между версиями

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

Текущая версия на 02:04, 11 июня 2012

Функторы

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();
    }
  }
  namespace Msk {
  }
}
 
Ru::spb::au::f();
::f(); //функция из глобального namespace

Если в Msk будет еще Ru, то чтобы вызвать функцию из spb из msk, надо будет писать не Ru::spb, а ::Ru::spb (коллизия двух Ru).

Поиск:

  • ищет имя в текущем namespace;
  • если не нашли, переходим выше;
  • если нашли, запускаем перегрузку.

При этом поиск просматривает ВСЕ имена (переменные, функции, классы...), так как синтаксически не ясно, что именно требуется. Функции находятся независимо от количества параметров. Если искали функцию, а наткнулись на соответствующие имя класса, происходит ошибка.

namespace Ru {
  // определена g(a,b)
  namespace spb {
    // определена g(a) 
    namespace spbtele { 
      // вызываем g(a,b) 
    }
  }
  namespace msk {}
}

В предыдущем примере поиск остановиться в spb. Поскольку там тоже есть g. Чтобы избежать такое, надо в spb записать:

  using ::Ru::g;

НЕ НАДО=НЕЛЬЗЯ писать using namespaсe std;

Безымянный namespace:

namespace {
  struct test {
    ...
  };
}

Появится уникальный namespace для каждого .cpp файла. Это позвляет создавать маленькие структуры, не боясь перекрытия имен. Компилятор авторматически добавит после него:

using namespace <name>;

Пространствам имён можно задавать псевдонимы:

namespace a = ru::spb::au;
a::f();

ADL - argument dependent lookup:

namespace g { 
  struct complex {};
  complex operator+();
}
g::complex a, b;   
a = a + b; //как ни странно, это сработает :)
а = g::operator+(a, b);

Поиск имён происходит там, где мы находимся, а также и в namespace аргументов (это первый шаг). Этот поиск называется поиском Кёнига.