Re[4]: встраивается ли boost/std::bind
От: jazzer Россия Skype: enerjazzer
Дата: 04.02.15 09:40
Оценка:
Здравствуйте, swingus, Вы писали:

S>Здравствуйте, jazzer, Вы писали:


J>>bind тоже не делает type erasure, равно как и boost::lambda.


S>Ага, я всё-таки прав был, если верить Скотту

S>

S>...Во-вторых, лямбда-выражения как правило работают быстрее. Дело в том что std::bind захватывает и хранит указатель на функцию, поэтому компилятор имеет мало шансов встроить (inline) ее, ...


какое отношение это имеет к type erasure? его по-прежнему нету, в отличие от boost/std::function.

Плюс bind берет в качестве аргумента не только указатель на функцию, но и функциональный объект — а его operator() замечательно встраивается.

Плюс при стандартном использовании, когда результат bind не сохраняется куда-то надолго (что, скорее всего, приведет к type erasure, потому что будет храниться в виде function), а передается в шаблонную функцию, которая тут же и раскрывается (типа std::sort и т.п.) — я не вижу проблем со встраиванием такого вызова — оно после всех inline-преобразований должно превратиться просто в вызов функции, известной на этапе компиляции.
По крайней мере, я бы удивился, если бы компилятор не смог встроить код функции, взятой через bind.

(через полчаса)
З.Ы. Практика — критерий истины. Будем встраивать функцию f, сначала по-простому (функции gN), а потом на массиве (функции aN):
using namespace std;
using namespace placeholders;

int f(int x, int y) { return x+y; }

int __attribute__((noinline)) g1(int x, int y)
{
  return f(x,y);
}

int __attribute__((noinline)) g2(int x, int y)
{
  auto w = bind(f, _1, _2);
  return w(x, y);
}

int __attribute__((noinline)) g3(int x, int y)
{
  auto w = bind(&f, _1, y);
  return w(x);
}

int __attribute__((noinline)) g4(int x, int y)
{
  auto w = bind(&f, x, _1);
  return w(y);
}

// теперь массив
int arr[] = {1,2,3,4,5,6,7,8,9};

int __attribute__((noinline)) a1(int y)
{
  transform( begin(arr), end(arr), begin(arr), [y](int& a){ return f(a, y);} );
  return arr[0];
}

int __attribute__((noinline)) a2(int y)
{
  transform( begin(arr), end(arr), begin(arr), bind(f, _1, y) );
  return arr[0];
}

компилирую g++4.9.1 --std=c++11 -O2
результат:
0000000000400600 <f(int, int)>:
  400600:       8d 04 37                lea    (%rdi,%rsi,1),%eax
  400603:       c3                      retq
  400604:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40060b:       00 00 00 00 00

0000000000400610 <g1(int, int)>:
  400610:       8d 04 37                lea    (%rdi,%rsi,1),%eax
  400613:       c3                      retq
  400614:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40061b:       00 00 00 00 00

0000000000400620 <g2(int, int)>:
  400620:       8d 04 3e                lea    (%rsi,%rdi,1),%eax
  400623:       c3                      retq
  400624:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40062b:       00 00 00 00 00

0000000000400630 <g3(int, int)>:
  400630:       8d 04 3e                lea    (%rsi,%rdi,1),%eax
  400633:       c3                      retq
  400634:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40063b:       00 00 00 00 00

0000000000400640 <g4(int, int)>:
  400640:       8d 04 37                lea    (%rdi,%rsi,1),%eax
  400643:       c3                      retq
  400644:       66 66 66 2e 0f 1f 84    data32 data32 nopw %cs:0x0(%rax,%rax,1)
  40064b:       00 00 00 00 00

0000000000400650 <a1(int)>:
  400650:       b8 a0 1b 40 00          mov    $0x401ba0,%eax
  400655:       0f 1f 00                nopl   (%rax)
  400658:       01 38                   add    %edi,(%rax)
  40065a:       48 83 c0 04             add    $0x4,%rax
  40065e:       48 3d c4 1b 40 00       cmp    $0x401bc4,%rax
  400664:       75 f2                   jne    400658 <a1(int)+0x8>
  400666:       8b 05 34 15 00 00       mov    0x1534(%rip),%eax        # 401ba0 <arr>
  40066c:       c3                      retq
  40066d:       0f 1f 00                nopl   (%rax)

0000000000400670 <a2(int)>:
  400670:       b8 a0 1b 40 00          mov    $0x401ba0,%eax
  400675:       0f 1f 00                nopl   (%rax)
  400678:       01 38                   add    %edi,(%rax)
  40067a:       48 83 c0 04             add    $0x4,%rax
  40067e:       48 3d c4 1b 40 00       cmp    $0x401bc4,%rax
  400684:       75 f2                   jne    400678 <a2(int)+0x8>
  400686:       8b 05 14 15 00 00       mov    0x1514(%rip),%eax        # 401ba0 <arr>
  40068c:       c3                      retq
  40068d:       00 00                   add    %al,(%rax)

найдите 10 отличий.

Так что либо Скотт неправ, либо ты читаешь что-то сильно устаревшее.

З.З.Ы. C boost::bind точно такой же результат, если что — это на случай подозрений, что компилятор знает что-то особенное про свой std::bind.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.