
Erik skrev:
I did some tests and got the exact same results for the following use of BOOST_FOREACH (and the corresponding use of my macro and a handcoded loop): ////////////////////////////////////////////////////// #include <boost/foreach.hpp>
#include <vector>
void f(float); struct A { void g() const; std::vector<float> const v; };
void A::g() const { BOOST_FOREACH(float i, v) f(i); } ///////////////////////////////////////////////////// Of course I got the exact same results with this code, because v is the first member of A, so A::v has the same address as A. When I realized this I modified the testcase:
////////////////////////////////////////////////////// #include <boost/foreach.hpp> #include <vector> void f(float); struct A { void g() const; char name[52]; std::vector<float> const v; }; void A::g() const { BOOST_FOREACH(float i, v) f(i); } ////////////////////////////////////////////////////// Unfortunately it does not look so good for BOOST_FOREACH after this modification. It will increase to 24 instructions, while the handcoded is still only 21. I created a script (attached) to test the examples systematically with different compiler versions and optimization levels. Here are the results that it gave me: Optimizations: O3 O2 Os handcoded: parameter: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 member: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 member_with_local: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 iterate_vector: parameter: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 member: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 member_with_local: g++-4.2.0: 21 21 20 g++-4.1.2: 21 21 20 BOOST_FOREACH: parameter: g++-4.2.0: 21 31 57 g++-4.1.2: 28 35 90 member: g++-4.2.0: 24 32 58 g++-4.1.2: 29 36 91 member_with_local: g++-4.2.0: 24 32 58 g++-4.1.2: 29 36 91 If you want to try it yourself, put the script in an empty directory and run from there; it will create some files. After running it, it may be interesting to compare the generated code, for example: diff -dU2 iterate_vector-member-g++-4.2.0-O3.s BOOST_FOREACH-member-g++-4.2.0-O3.s|kompare - #! /bin/sh ITERATIONS="0 1 2" ITERATION_NAMES=(handcoded iterate_vector BOOST_FOREACH) ITERATION_CODES=(\ " std::vector<float>::const_iterator const v_end = v.end(); for (std::vector<float>::const_iterator it = v.begin(); it != v_end; ++it) f(*it);" \ " #define iterate_vector_const(value_type, it, v) \\ for \\ (struct { \\ std::vector<value_type>::const_iterator current; \\ std::vector<value_type>::const_iterator const end; \\ value_type const & operator*() {return *current;} \\ } it = {v.begin(), v.end()}; \\ it.current != it.end; \\ ++it.current) \\ iterate_vector_const(float, it, v) f(*it);" \ " BOOST_FOREACH(float i, v) f(i);") EXAMPLES="0 1 2" EXAMPLE_NAMES=(parameter member member_with_local) EXAMPLE_CODES=(\ " void g(const std::vector<float> & v) {" \ " struct A { void g() const; char name[52]; std::vector<float> const v; }; void A::g() const {" \ " struct A { void g() const; char name[52]; std::vector<float> const m_v; }; void A::g() const { std::vector<float> const & v = m_v; ") COMPILER_VERSIONS="4.2.0 4.1.2" OPTIMIZATOINS="3 2 s" unset TABLE_HEADER for optimization in $OPTIMIZATOINS; do TABLE_HEADER="$TABLE_HEADER O$optimization" done echo "Optimizations: $TABLE_HEADER" for iteration in $ITERATIONS; do echo ${ITERATION_NAMES[$iteration]}: for example in $EXAMPLES; do NAME=${ITERATION_NAMES[$iteration]}-${EXAMPLE_NAMES[$example]} IN=$NAME.cc rm -f $IN echo "void f(float);" >> $IN echo "#include <boost/foreach.hpp>" >> $IN echo "#include <vector>" >> $IN echo "${EXAMPLE_CODES[$example]}" >> $IN echo "${ITERATION_CODES[$iteration]}" >> $IN echo "}" >> $IN echo " ${EXAMPLE_NAMES[$example]}:" for compiler_version in $COMPILER_VERSIONS; do MESSAGE=g++-$compiler_version: for optimization in $OPTIMIZATOINS; do OUT=$NAME-g++-$compiler_version-O$optimization.s g++-$compiler_version -Wall -Wextra -O$optimization -S $IN -o $OUT MESSAGE="$MESSAGE $(egrep -v "^([ ]*\\.|_)" $OUT|wc -l)" done echo " $MESSAGE" done done done