Consider the following code to iterate over an intrusive list using the BOOST_FOREACH macro:
#include <boost/foreach.hpp>
#include <boost/intrusive/list.hpp>
typedef boost::intrusive::list<
boost::intrusive::list_base_hook<> > MyList;
void iterate (const MyList& xs) {
BOOST_FOREACH (MyList::const_reference node, xs);
}
int main () {
MyList xs;
iterate (xs);
return 0;
}
Given boost version 1.48 the code fails with clang 3.2 (SVN) and gcc 4.6.3, but works with gcc 4.5.3. With non-const-qualified parameter xs
to iterate
the code works. With C++11 enabled all of the compilers accept the code. When using boost-1.46 both gcc versions accept the code, but clang still doesn't.
Is the code at hand a misuse of the BOOST_FOREACH
macro, or is the error at boosts side? Is there a workaround that is nicer than iteration with regular for-loop?
Edit: I pasted the error messages to pastebin (both are very verbose) for GCC and clang.
Here is what I could gather from the logs as well as my deductions as to the cause of failure.
Short version: for some reason
BOOST_FOREACH
attempts to copy the data which is not possible.There is a note on the Extensibility page:
From the diagnosis, it is unclear whether the type is properly configured, so you might want to give it a go.
Pruned diagnosis and analysis.
I tried to isolate the error as much as possible (removing backtraces etc..) Apparently the problem stems from
boost::intrusive::list
, and more precisely the inability to build a newboost::intrusive::list<>
from aboost::intrusive::list<> const
.The most promising constructor is defined by a macro:
which expands to
which is the way boost emulates move semantics for non-copyable types in C++03. However it cannot move from a
const
item since theconst
qualifier would be lost.This looks to be part of the trickery used by
BOOST_FOREACH
to avoid multiple evaluation of the container argument (in case it is a function invocation) though I am a little surprised it tries to copy the argument here.