toge's diary

コンピュータ関連の趣味をつらつらと。

お手軽for each

http://tricklib.com/cxx/ex/evil_for/

とっても楽に使えるC++版foreach。ネストも当然出来たりする。
パフォーマンスがちょっと心配だったんで実験してみました。

#include "vector"
#include "evil_for.h"

std::vector array;

void
loop_test1()
{
  std::vector::iterator p, pend = array.end();
  for (p = array.begin(); p != pend; ++p)
    *p = 5;
}

void
loop_test2()
{
  evil_for(array)
    *evil_i(array) = 5;
} 

まずevil_forのコード量の少なさに感動してしまいました。
んでg++-4.1.0 -O3 -march=athlon-xp -Sした結果が以下の通り。(ちょっと加工してます)

_Z10loop_test1v:
.LFB511:
	movl	array+4, %edx
	movl	array, %eax
	pushl	%ebp
	cmpl	%eax, %edx
	movl	%esp, %ebp
	je	.L20
.L19:
	movl	$5, (%eax)
	addl	$4, %eax
	cmpl	%eax, %edx
	jne	.L19
.L20:
	leave
	ret

_Z10loop_test2v:
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ebx
	leal	-16(%ebp), %ebx
	subl	$36, %esp
	movl	array, %eax
	movl	$_ZN14evil_for_tools15destruct_objectIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEEEvPv, -12(%ebp)
	movl	%ebx, 4(%esp)
	movl	%eax, -8(%ebp)
	leal	-8(%ebp), %eax
	movl	%eax, (%esp)
	call	_ZN14evil_for_tools16duplicate_objectIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEEEvPvS8_
	movl	array+4, %edx
	cmpl	%edx, -16(%ebp)
	je	.L23
	movl	-16(%ebp), %eax
.L24:
	movl	$5, (%eax)
	addl	$4, %eax
	cmpl	%edx, %eax
	jne	.L24
	movl	%eax, (%ebx)
.L23:
	movl	%ebx, (%esp)
	call	*-12(%ebp)
	addl	$36, %esp
	popl	%ebx
	leave
	ret 

ループ内は全く同じになってますね。素晴しい。evil_forを使うとちょっと前後にコードが入ってしまうのが残念。(特に関数呼び出し)
まあ呼ぶ関数自体も対した処理をしていないので殆どオーバーヘッドはないと思います。
これは良い物を知りました。ばりばり使わせて貰おうと思います。