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
#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
Erik skrev:
this I modified the testcase:
//////////////////////////////////////////////////////
#include
#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::const_iterator current; \\
std::vector::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 " >> $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