Modify

Ticket #6131 (closed Bugs: fixed)

Opened 2 years ago

Last modified 16 months ago

#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

foreachtest.cpp Download (174 bytes) - added by loonycyborg 2 years ago.
Test case.

Change History

Changed 2 years ago by loonycyborg

Test case.

comment:1 in reply to: ↑ description Changed 2 years ago by Michel Morin <mimomorin@…>

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 Changed 2 years ago by eric_niebler

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 Changed 2 years ago by eric_niebler

  • Status changed from new to closed
  • Resolution set to fixed

(In [75634]) merge [75540] from trunk, fixes #6131

comment:4 follow-up: ↓ 5 Changed 2 years ago by anonymous

  • Status changed from closed to reopened
  • Version changed from Boost 1.48.0 to Boost 1.49.0
  • Resolution fixed deleted

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 in reply to: ↑ 4 Changed 2 years ago by anonymous

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 Changed 2 years ago by eric_niebler

It's impossible to say without looking at a repro. Can you attach code that demonstrates the problem?

comment:7 Changed 2 years ago by eric_niebler

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 Changed 2 years ago by eric_niebler

  • Status changed from reopened to closed
  • Resolution set to fixed

(In [77591]) merge [77416] from trunk, fixes #6131, fixes #6455

comment:9 Changed 23 months ago by anonymous

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 Changed 23 months ago by eric_niebler

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 Changed 22 months ago by anonymous

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 Changed 22 months ago by eric_niebler

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 Changed 22 months ago by monster.romster@…

  • Cc monster.romster@… added
  • Version changed from Boost 1.49.0 to 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 Changed 22 months ago by eric_niebler

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 Changed 21 months ago by anonymous

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 Changed 19 months ago by anonymous

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 Changed 19 months ago by michel

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.

comment:18 follow-up: ↓ 19 Changed 19 months ago by eric_niebler

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 in reply to: ↑ 18 Changed 18 months ago by linasvepstas@…

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_FOREACH

Let 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 Changed 18 months ago by anonymous

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 Changed 18 months ago by linasvepstas@…

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 Changed 17 months ago by anonymous

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 Changed 16 months ago by eric_niebler

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.

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.