отображение содержащейся структуры с бустом - PullRequest
2 голосов
/ 08 июня 2009

Учитывая эти две структуры:

struct point {
    int x,y;
};

struct pinfo {
    struct point p;
    unsigned long flags;
};

И функция, которая меняет точку:

void p_map(struct point &p);

Можно ли использовать boost (например, boost :: bind или boost :: lambda) для создания функции, эквивалентной:

void pi_map(struct pinfo &pi) { p_map(pi.p); }

-edit: обновление для дополнительной информации:

Первоначальным намерением для этой функции было использовать ее в for_each. Например, учитывая эту функцию:

void p_map(struct point &p)
{
    p.x += 1;
    p.y += 1;
}

Я мог бы написать:

void foreach(std::vector<struct pinfo> &pi_vec)
{
    for_each(pi_vec.begin(), pi_vec.end(), pi_map);
}

Как было предложено в ответе, возможно связать переменные-члены с boost :: lambda, и создать альтернативную версию for_each:

void foreach2(std::vector<struct pinfo> &pi_vec)
{
     boost::function<void (pinfo&)> pi_map2 = bind(&p_map, bind(&pinfo::p, _1));
     for_each(pi_vec.begin(), pi_vec.end(), pi_map2);
}

Моя проблема с этим подходом заключается в том, что он gcc (v. 4.3.2) не включает Функции pi_map и p_map для версии foreach2. ​​

Код x86, сгенерированный для функции foreach1:

0000000000400dd0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)>:
  400dd0:       48 8b 57 08         mov    0x8(%rdi),%rdx
  400dd4:       48 8b 07            mov    (%rdi),%rax
  400dd7:       48 39 c2            cmp    %rax,%rdx
  400dda:       74 14               je     400df0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)+0x20>
  400ddc:       0f 1f 40 00         nopl   0x0(%rax)
  400de0:       83 00 01            addl   $0x1,(%rax)
  400de3:       83 40 04 01         addl   $0x1,0x4(%rax)
  400de7:       48 83 c0 10         add    $0x10,%rax
  400deb:       48 39 c2            cmp    %rax,%rdx
  400dee:       75 f0               jne    400de0 <foreach(std::vector<pinfo, std::allocator<pinfo> >&)+0x10>
  400df0:        f3 c3              repz retq

Который реализует for_each без вызова каких-либо функций. С другой стороны, код, сгенерированный для foreach2, является более сложным, из-за оптимизации, и, похоже, не встроены в функции отображения.

Однако этот вопрос кажется скорее философским, чем практическим с современными процессорами для настольных ПК, поскольку (как ни странно) производительность на моей машине одинаково для обеих версий.

1 Ответ

6 голосов
/ 08 июня 2009

Вы можете сделать это с boost :: lambda, переменные-члены могут быть связаны с bind так же, как функции-члены:

 #include <boost/function.hpp>
 #include <boost/lambda/bind.hpp>

 using namespace boost::lambda;

 boost::function<void (pinfo&)> pi_map = bind(&p_map, bind(&pinfo::p, _1));
...