Быстрые делегаты C++ - Сходства и различия

ОГЛАВЛЕНИЕ

Сходства и различия

typedef fd::delegate1 < void, int > MyDelegate;
CBase1 b1, b2; CDerived1 d1("d1");

// ----------------------------------------------------------------------


MyDelegate dg1(&CBase1::foo, &b1);
MyDelegate dg2 = &::hello;

if(dg1 == dg2)
cout << "dg1 equals to dg2" << endl;
else
cout << "dg1 does not equal to dg2" << endl;

if(dg1 > dg2)
{
  cout << "dg1 is greater than dg2" << endl;
  dg1(123);
}
else if(dg1 < dg2)
{
  cout << "dg2 is greater than dg1" << endl;
  dg2(234);
}

// ----------------------------------------------------------------------


MyDelegate dg3 = dg1;
MyDelegate dg4(&CBase1::foo, &b2);

// указатель функции и связанный с ним указатель вызываемого объекта,
// сохраняемые в dg1, совпадают с теми, которые сохраняются в dg3

if(0 == dg1.compare(dg3))
{  // эта проверка возвращает истину

  dg3(345);
}
if(0 == dg1.compare(dg3, true))
{  // эта проверка также возвращает истину

  dg3(456);
}

// ----------------------------------------------------------------------


// указатель функции, сохраненный в dg1, совпадает с сохраненным в dg4,

// но связанные с ними указатели на вызываемый объект не совпадают

if(0 == dg1.compare(dg4))
{  // эта проверка возвращает истину

  dg4(567);
}
if(0 == dg1.compare(dg4, true))
{  // эта проверка возвращает ложь

  dg4(678);
}

// ----------------------------------------------------------------------


if(dg2 != 0)
{   // эта проверка возвращает истину

  cout << "dg2 is not empty" << endl;
}

if(dg2)
{   // эта проверка возвращает истину

  cout << "dg2 is not empty" << endl;
}

if(!!dg2)
{ // эта проверка возвращает истину

  cout << "dg2 is not empty" << endl;
}

if(!dg2.empty())
{ // эта проверка возвращает истину

  cout << "dg2 is not empty" << endl;
}

// ----------------------------------------------------------------------


dg1.swap(dg2);

MyDelegate(dg2).swap(dg1);  // dg1 = dg2;


MyDelegate().swap(dg1); // dg1.clear();


dg2.clear();

dg3 = 0;

// ----------------------------------------------------------------------


if(dg3.empty())
{
  try
  {
    dg3(789);
  }
  catch(std::exception & e) { cout << e.what() << endl; }
  //исключение 'вызов пустого делегата'

}

// ----------------------------------------------------------------------


CBase1 * pBase = 0;
// намеренное связывание нулевого вызываемого объекта

dg3.bind(&CBase1::foo, pBase);
try
{
  FD_ASSERT( !dg3.empty() );
  dg3(890);
}
 // исключение 'вызов функции-члена при отсутствующем объекте'

catch(std::exception & e) { cout << e.what() << endl; }

Сравнение двух делегатов означает сравнение адреса ячейки памяти, сохраненного внутри указателя функции, и это на самом деле не означает ничего особенного. Но это позволяет использовать наш делегат в контейнере STL без проблем. Так как это 'быстрый' делегат в 'большинстве' случаев, нам не нужно сильно беспокоиться о снижении производительности при копировании делегата внутрь контейнера STL согласно семантике значений.