#6131 closed Bugs (fixed)
#define foreach BOOST_FOREACH causes weird compile error in certain circumstances with boost 1.48
Reported by: | loonycyborg | Owned by: | Eric Niebler |
---|---|---|---|
Milestone: | To Be Determined | Component: | foreach |
Version: | Boost 1.50.0 | Severity: | Problem |
Keywords: | Cc: | monster.romster@… |
Description
#define foreach BOOST_FOREACH causes compile error "'boost::BOOST_FOREACH' has not been declared" on its line if it appears after #include <boost/foreach.hpp> and before certain other boost headers.
Compiler version: gcc (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) 4.5.3 Also tried gcc 4.3.5, 4.4.6 and 4.6.2
Attachments (1)
Change History (24)
by , 11 years ago
Attachment: | foreachtest.cpp added |
---|
comment:1 by , 11 years ago
before certain other boost headers.
Specifically, those Boost headers are
boost/multi_index/hashed_index.hpp
boost/multi_index/ordered_index.hpp
boost/multi_index/random_access_index.hpp
boost/multi_index/sequenced_index.hpp
and headers that eventually include them, right?
Here are related threads in Boost-users ML:
comment:2 by , 11 years ago
Attempted a workaround on trunk here: <https://svn.boost.org/trac/boost/changeset/75540>. I'll merge to release if the tests don't explode. I don't see why they would.
comment:3 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
follow-up: 5 comment:4 by , 11 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Version: | Boost 1.48.0 → Boost 1.49.0 |
I use just this #define in my code and I have actually _started_ to get compiler error with boost 1.49 (Xcode 4.3, LLVM compiler 3.1):
Redefinition of 'is_lightweight_proxy' Redefinition of 'is_noncopyable'
And even more errors that say:
No matching function for call to 'should_copy_impl'
comment:5 by , 11 years ago
Replying to anonymous:
I use just this #define in my code and I have actually _started_ to get compiler error with boost 1.49 (Xcode 4.3, LLVM compiler 3.1):
Redefinition of 'is_lightweight_proxy' Redefinition of 'is_noncopyable'
And even more errors that say:
No matching function for call to 'should_copy_impl'
FWIW the error actually comes up when using BOOST_REVERSE_FOREACH (which I use alongside foreach):
../Game/Widgets.hpp:130:9: error: no matching function for call to 'should_copy_impl'
PASS_TOUCH(touchBegan)
~
../Game/Widgets.hpp:124:17: note: expanded from macro 'PASS_TOUCH'
BOOST_REVERSE_FOREACH (const WidgetPtr& child, children) \
/usr/local/include/boost/foreach.hpp:1117:77: note: expanded from macro 'BOOST_REVERSE_FOREACH'
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) {} else \
/usr/local/include/boost/foreach.hpp:1051:9: note: expanded from macro 'BOOST_FOREACH_REND'
, BOOST_FOREACH_SHOULD_COPY(COL))
/usr/local/include/boost/foreach.hpp:961:6: note: expanded from macro 'BOOST_FOREACH_SHOULD_COPY'
(boost::foreach_detail_::should_copy_impl( \
~
So maybe this is actually another bug?
comment:6 by , 11 years ago
It's impossible to say without looking at a repro. Can you attach code that demonstrates the problem?
comment:7 by , 11 years ago
In light of #6455, it seems this "fix" is doing more harm than good. I've reverted foreach to the 1.47 version on trunk and plan to close this bug "won't fix". Sorry, I tried.
comment:8 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
comment:9 by , 10 years ago
In 1.49 under Visual Studio 2008, I am now getting this error whenever I DON'T include <boost/foreach.hpp> until AFTER I #define foreach BOOST_FOREACH:
'boost::BOOST_FOREACH::is lightweight proxy' : class template has already been defined
foreach_fwd.hpp(62) : see declaration of 'boost::BOOST_FOREACH::is_lightweight_proxy'
Simple test that fails:
#define foreach BOOST_FOREACH #include <boost/foreach.hpp>
It works fine in the other order, i.e., the include before the #define. This never used to be a problem.
comment:10 by , 10 years ago
Foreach was broken in 1.49. As you can see from the comment above, the change was reverted and the fix has already been migrated to the release branch. In 1.50 (currently in beta), the problem should be fixed.
comment:11 by , 10 years ago
The problem still occur in 1.50.0. I stumbled on it while building mkvtoolnix 5.0.1 using clang 3.1 from Xcode 4.3.3. The patches from changeset 75540 are still a valid cure.
comment:12 by , 10 years ago
As you can see from the comments above yours, the patch in [75540], which was released as part of Boost 1.49, caused more problems than it solved. The bug is unfortunate, but there is nothing that can be done at this point, AFAIK. Sorry.
comment:13 by , 10 years ago
Cc: | added |
---|---|
Version: | Boost 1.49.0 → Boost 1.50.0 |
I tried that patch https://svn.boost.org/trac/boost/changeset/75540 but then boost fails to compile:
"ccache" "g++" -ftemplate-depth-128 -O2 -march=i686 -pipe -O3 -Wno-deprecated -fno-strict-aliasing -finline-functions -Wno-inline -Wall -fPIC -DBOOST_ALL_NO_LIB=1 -DBOOST_GRAPH_DYN_LINK=1 -DBOOST_HAS_ICU=1 -DNDEBUG -I"." -I"/usr/include" -I"libs/graph/src" -c -o "bin.v2/libs/graph/build/gcc-4.5.3/release/graphml.o" "libs/graph/src/graphml.cpp" In file included from libs/graph/src/graphml.cpp:14:0: ./boost/foreach.hpp:126:16: error: 'boost::boost::mpl' has not been declared ./boost/foreach.hpp:126:21: error: expected '{' before 'false_' ./boost/foreach.hpp:127:5: error: invalid type in declaration before '{' token ./boost/foreach.hpp:127:5: error: template declaration of 'int boost::boost::foreach::false_' ./boost/foreach.hpp:127:5: warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x ./boost/foreach.hpp:137:16: error: 'boost::boost::mpl' has not been declared ./boost/foreach.hpp:137:21: error: expected '{' before 'or_' ./boost/foreach.hpp:137:24: error: expected initializer before '<' token In file included from libs/graph/src/graphml.cpp:14:0: ./boost/foreach.hpp:168:8: error: 'BOOST_FOREACH' in namespace 'boost::boost' does not name a type
So I am forced to keep boost at 1.49.0 due to wesnoth failing on 1.50.0
[ 15%] Building CXX object src/CMakeFiles/wesnoth-game.dir/font.cpp.o In file included from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/shared_object.hpp:21:0, from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/tstring.hpp:19, from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/config.hpp:40, from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/terrain.hpp:18, from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/map.hpp:23, from /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/builder.cpp:26: /usr/ports/work/wesnoth/src/wesnoth-1.10.3/src/foreach.hpp:9:22: error: 'boost::BOOST_FOREACH' has not been declared make[2]: *** [src/CMakeFiles/wesnoth-game.dir/builder.cpp.o] Error 1 make[2]: *** Waiting for unfinished jobs.... make[1]: *** [src/CMakeFiles/wesnoth-game.dir/all] Error 2 make: *** [all] Error 2 =======> ERROR: Building '/var/ports/packages/wesnoth#1.10.3-1.pkg.tar.gz' failed.
Lets hope boost 1.51.0 fixes this, or is wesnoth 1.10.3 doing something wrong?
Regards, Danny Rawlins Romster @ freenode distro http://crux.nu
comment:14 by , 10 years ago
There is no fix that doesn't cause more problems than it solves, to the best of my knowledge. No changes are planned for 1.51. Simply do not #define foreach to anything and you should avoid this problem entirely.
comment:15 by , 10 years ago
Someone should then update the documentation (http://www.boost.org/doc/libs/1_50_0/doc/html/foreach.html#foreach.introduction.making__literal_boost_foreach__literal__prettier) and clarify that "#define foreach should not be used". Thanks.
comment:16 by , 10 years ago
Congrats, boost, you managed to break compatibility in one of the simplest-to-use libraries, and nobody gives a damn enough to at least fix the docs. Good job.
comment:17 by , 10 years ago
The following treatment does not solve the problem, but it slightly improves the situation:
In boost/multi_index/hashed_index.hpp
, change
/* Boost.Foreach compatibility */ template< typename KeyFromValue,typename Hash,typename Pred, typename SuperMeta,typename TagList,typename Category > inline boost::mpl::true_* boost_foreach_is_noncopyable( boost::multi_index::detail::hashed_index< KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&, boost::foreach::tag) { return 0; }
into
#if !(!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ || BOOST_WORKAROUND(BOOST_MSVC, >= 1310) && !defined(_PREFAST_) \ || (BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ <= 5) && !defined(BOOST_INTEL) && \ !defined(BOOST_CLANG)) \ || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL) && \ !defined(BOOST_CLANG))) /* Boost.Foreach compatibility */ template< typename KeyFromValue,typename Hash,typename Pred, typename SuperMeta,typename TagList,typename Category > inline boost::mpl::true_* boost_foreach_is_noncopyable( boost::multi_index::detail::hashed_index< KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&, boost::foreach::tag) { return 0; } #endif
and do the same thing for boost/multi_index/ordered_index.hpp
, boost/multi_index/random_access_index.hpp
and boost/multi_index/sequenced_index.hpp
.
follow-up: 19 comment:18 by , 10 years ago
Can someone try defining their foreach
macro like this:
#include <boost/foreach.hpp> namespace boost { namespace BOOST_FOREACH = foreach; } #define foreach BOOST_FOREACH
Let me know how that works for you.
comment:19 by , 10 years ago
Replying to eric_niebler:
Can someone try defining their
foreach
macro like this:#include <boost/foreach.hpp> namespace boost { namespace BOOST_FOREACH = foreach; } #define foreach BOOST_FOREACHLet me know how that works for you.
Does not work for boost-1.49 I get: error: declaration of namespace ‘boost::BOOST_FOREACH’ conflicts with ...
/usr/local/include/boost/foreach_fwd.hpp:56:1: error: previous declaration of namespace ‘boost::BOOST_FOREACH’ here
comment:20 by , 10 years ago
Anyway, I hacked around this by surrounding above with #if BOOST_VERSION != 104900 which seems to work for that one installation, and also has been reported to work with other installations (MacOS, archlinux) running boost-1.50, which break if the above is NOT done.
Original ticket: https://bugs.launchpad.net/opencog/+bug/1057640/
comment:21 by , 10 years ago
To be completely clear: the following seems to work for multiple versions of boost (1.46, 1.48, 1.49, 1.50) and for multiple OS'es (MacOS, arch linux, multiple different ubuntu, RHEL4, and a cluster running old CentOS):
#include <boost/foreach.hpp> #include <boost/version.hpp> namespace boost { #if BOOST_VERSION != 104900 namespace BOOST_FOREACH = foreach; #endif } // namespace boost #define foreach BOOST_FOREACH
comment:22 by , 10 years ago
Note from boost foreach 1.52 documentation:
I discourage this. It leads to name conflicts within the BOOST_FOREACH macro itself, where foreach is the name of a namespace
Why can't you simply rename the boost::foreach namespace into something different? These changes would be much smaller than forcing the users of boost to rename their foreach macros in thousands of source files.
comment:23 by , 10 years ago
Renaming the foreach
namespace would be a breaking change. There are templates in the foreach
namespace that end-users have specialized to make BOOST_FOREACH
work with their types. All that would break if the foreach
namespace changed.
Test case.