[boost::foreach] and bcc32-5.6.4

Has anyone tried BOOST_FOREACH with bcc32-5.6.4? I've just tried the example BOOST_FOREACH(char ch, "Hello") { std::cout << ch; } And get a string of errors of the following: (line 11 of main.cpp is the BOOST_FOREACH line). I'd really like to be able to use this library so if anyone can give any help in getting it to work, it would be really useful. Thanks Russell [C++] main.cpp(1): [C++ Error] main.cpp(11): E2354 Two operands must evaluate to the same type [C++ Warning] main.cpp(11): W8032 Temporary used for parameter 1 in call to 'boost::for_each::boost::for_each::container<char *,boost::mpl::false_> wrap<char *>(char * &)' [C++ Error] main.cpp(11): E2354 Two operands must evaluate to the same type [C++ Error] main.cpp(11): E2285 Could not find a match for 'boost::for_each::contain<T>(undefined,bool,undefined)' [C++ Warning] main.cpp(11): W8032 Temporary used for parameter 1 in call to 'boost::for_each::boost::for_each::container<char *,boost::mpl::false_> wrap<char *>(char * &)'

Russell Hind wrote:
Has anyone tried BOOST_FOREACH with bcc32-5.6.4? I've just tried the example
<snip> I just uploaded to the Boost Sandbox File Vault a new and improved version of BOOST_FOREACH. Since much of the code is new, I removed many of the old work-arounds, so things are likely to break until the dust settles. I have verified it works on VC6+ and gcc 3.3.3. I would be especially interested in seeing results from BCC, EDG-based compilers, and GCC 2.9x. You can find foreach.zip at: http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler There is a simple regression test there and a Jamfile. If it doesn't compile, try defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION. If it still doesn't compiler, try defining BOOST_FOREACH_NO_RVALUE_DETECTION. Let me know the compiler version, and which macros you needed to define to get it to work. Thanks! -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
I just uploaded to the Boost Sandbox File Vault a new and improved version of BOOST_FOREACH. Since much of the code is new, I removed many of the old work-arounds, so things are likely to break until the dust settles. I have verified it works on VC6+ and gcc 3.3.3.
I would be especially interested in seeing results from BCC, EDG-based compilers, and GCC 2.9x. You can find foreach.zip at:
http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
There is a simple regression test there and a Jamfile. If it doesn't compile, try defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION. If it still doesn't compiler, try defining BOOST_FOREACH_NO_RVALUE_DETECTION. Let me know the compiler version, and which macros you needed to define to get it to work.
Hi Eric, with the new version, I can't even get foreach.hpp to compile. I get the following error on line 308: [C++ Error] foreach.hpp(308): E2109 Not an allowed type This is borland C++ bcc32 version 5.6.4 using STLPort supplied with the compiler and I've placed foreach.hpp inside the boost folder of a 1.32.0 distribution. Cheers Russell

Russell Hind wrote:
Hi Eric, with the new version, I can't even get foreach.hpp to compile. I get the following error on line 308:
[C++ Error] foreach.hpp(308): E2109 Not an allowed type
This is a shot in the dark, but can you try the attached version? If this doesn't work, I'll need the help of someone familiar with this compiler. -- Eric Niebler Boost Consulting www.boost-consulting.com /////////////////////////////////////////////////////////////////////////////// // foreach.hpp header file // // Copyright 2004 Eric Niebler. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_FOREACH #include <cstddef> #include <utility> // for std::pair #include <iterator> // for std::iterator_traits #include <boost/config.hpp> #include <boost/detail/workaround.hpp> // Some compilers allow temporaries to be bound to non-const references. // These compilers make it impossible to for BOOST_FOREACH to detect // temporaries and avoid reevaluation of the collection expression. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) # define BOOST_FOREACH_NO_RVALUE_DETECTION #endif // Some compilers do not correctly implement the L-value/R-value conversion // rules of the ternary conditional operator. #if defined(BOOST_FOREACH_NO_RVALUE_DETECTION) \ || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ || BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800)) # define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION #endif #include <boost/mpl/or.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/range/end.hpp> #include <boost/range/begin.hpp> #include <boost/range/result_iterator.hpp> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_pointer.hpp> #include <boost/iterator/iterator_traits.hpp> #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION # include <new> # include <boost/aligned_storage.hpp> #endif namespace boost { // forward declarations for iterator_range template<typename T> class iterator_range; // forward declarations for sub_range template<typename T> class sub_range; namespace foreach { /////////////////////////////////////////////////////////////////////////////// // yes/no // typedef char yes_type; typedef char (&no_type)[2]; /////////////////////////////////////////////////////////////////////////////// // adl_begin/adl_end // template<typename T> inline BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type adl_begin(T &t) { #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) return boost::begin(t); #else using boost::begin; typedef BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type type; return type(begin(t)); #endif } template<typename T> inline BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type adl_end(T &t) { #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) return boost::end(t); #else using boost::end; typedef BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type type; return type(end(t)); #endif } /////////////////////////////////////////////////////////////////////////////// // auto_any_t/auto_any // struct auto_any_base { // auto_any_base must evaluate to false in boolean context so that // they can be declared in if() statements. operator bool() const { return false; } }; template<typename T> struct auto_any : auto_any_base { auto_any(T const &t) : item(t) { } // temporaries of type auto_any will be bound to const auto_any_base // references, but we still want to be able to mutate the stored // data, so declare it as mutable. mutable T item; }; typedef auto_any_base const &auto_any_t; template<typename T,typename C> inline BOOST_DEDUCED_TYPENAME mpl::if_<C,T const,T>::type &auto_any_cast(auto_any_t a) { return static_cast<auto_any<T> const &>(a).item; } typedef mpl::true_ const_; /////////////////////////////////////////////////////////////////////////////// // type2type // template<typename T,typename C = mpl::false_> struct type2type : mpl::if_<C,T const,T> { }; template<typename T,typename C = mpl::false_> struct foreach_iterator { // If there is no function template ordering, then it may // be impossible to strip cv-modifiers from T, so use // range_result_iterator. Otherwise, use range_const_iterator // and range_iterator. #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< C , range_const_iterator<T> , range_iterator<T> >::type type; #else typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< C , range_result_iterator<T const> , range_result_iterator<T> >::type type; #endif }; template<typename T,typename C = mpl::false_> struct foreach_reference : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type> { }; /////////////////////////////////////////////////////////////////////////////// // encode_type // template<typename T> inline type2type<T> *encode_type(T &) { return 0; } #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template<typename T> inline type2type<T,const_> *encode_type(T const &) { return 0; } #endif /////////////////////////////////////////////////////////////////////////////// // in_range // template<typename T> inline std::pair<T,T> in_range(T begin, T end) { return std::make_pair(begin, end); } #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION /////////////////////////////////////////////////////////////////////////////// // rvalue_probe // struct rvalue_probe { template<typename T> rvalue_probe(T const &t, bool &b) : ptemp(const_cast<T *>(&t)) , rvalue(b) { } template<typename U> operator U() { rvalue = true; return *static_cast<U *>(ptemp); } template<typename V> operator V &() const { return *static_cast<V *>(ptemp); } void *ptemp; bool &rvalue; }; /////////////////////////////////////////////////////////////////////////////// // simple_variant // holds either a T or a T* template<typename T> struct simple_variant { simple_variant(T *t) : rvalue(false) { *static_cast<T **>(data.address()) = t; } simple_variant(T const &t) : rvalue(true) { ::new(data.address()) T(t); } simple_variant(simple_variant const &that) : rvalue(that.rvalue) { if(rvalue) ::new(data.address()) T(*that.get()); else *static_cast<T **>(data.address()) = that.get(); } ~simple_variant() { if(rvalue) get()->~T(); } T *get() const { if(rvalue) return static_cast<T *>(data.address()); else return *static_cast<T **>(data.address()); } private: enum { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) }; simple_variant &operator =(simple_variant const &); bool const rvalue; mutable aligned_storage<size> data; }; #elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION) /////////////////////////////////////////////////////////////////////////////// // is_rvalue // template<typename T> no_type is_rvalue(T &, int); template<typename T> yes_type is_rvalue(T const &, ...); #endif // BOOST_FOREACH_NO_CONST_RVALUE_DETECTION /////////////////////////////////////////////////////////////////////////////// // set_false // inline bool set_false(bool &b) { return b = false; } no_type is_range_fun(...); template<typename T> yes_type is_range_fun(std::pair<T,T> *); template<typename T> yes_type is_range_fun(iterator_range<T> *); template<typename T> yes_type is_range_fun(sub_range<T> *); template<typename T> struct is_range_base { BOOST_STATIC_CONSTANT(size_t, size = sizeof(boost::foreach::is_range_fun((T*)0))); BOOST_STATIC_CONSTANT(bool, value = sizeof(yes_type)==size); typedef mpl::bool_<value> type; }; template<typename T> struct is_range : is_range_base<T>::type { }; template<typename T> struct is_cheap_copy : mpl::or_<is_pointer<T>, is_range<T> > { // work-around for VC6 enum { value = mpl::or_< is_pointer<T>, is_range<T> >::value }; }; /////////////////////////////////////////////////////////////////////////////// // cheap_copy // Overload this for user-defined collection types if they are inexpensive to copy. // This tells BOOST_FOREACH it can avoid the r-value/l-value detection stuff. template<typename T,typename C> inline mpl::bool_<is_cheap_copy<T>::value> cheap_copy(type2type<T,C> *) { return mpl::bool_<is_cheap_copy<T>::value>(); } /////////////////////////////////////////////////////////////////////////////// // contain // template<typename T> inline auto_any<T> contain(T const &t, bool const &, mpl::true_) { return t; } #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION template<typename T> inline auto_any<T *> contain(T &t, bool const &, mpl::false_) { return &t; } template<typename T> inline auto_any<simple_variant<T const> > contain(T const &t, bool const &rvalue, mpl::false_) { return rvalue ? simple_variant<T const>(t) : simple_variant<T const>(&t); } #else template<typename T> inline auto_any<T *> contain(T &t, mpl::false_, mpl::false_) // l-value { return &t; } template<typename T> inline auto_any<T> contain(T const &t, mpl::true_, mpl::false_) // r-value { return t; } #endif ///////////////////////////////////////////////////////////////////////////// // begin // template<typename T,typename C> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type> begin(auto_any_t col, type2type<T,C> *, bool, mpl::true_) { return foreach::adl_begin(auto_any_cast<T,C>(col)); } #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::false_>::type> begin(auto_any_t col, type2type<T> *, bool, mpl::false_) { return foreach::adl_begin(*auto_any_cast<T *,mpl::false_>(col)); } template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::true_>::type> begin(auto_any_t col, type2type<T,const_> *, bool, mpl::false_) { return foreach::adl_begin(*auto_any_cast<simple_variant<T const>,mpl::false_>(col).get()); } #else template<typename T,typename C> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type> begin(auto_any_t col, type2type<T,C> *, mpl::false_, mpl::false_) // l-value { typedef BOOST_DEDUCED_TYPENAME type2type<T,C>::type type; return foreach::adl_begin(*auto_any_cast<type *,mpl::false_>(col)); } template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::true_>::type> begin(auto_any_t col, type2type<T,const_> *, mpl::true_, mpl::false_) // r-value { return foreach::adl_begin(auto_any_cast<T,mpl::true_>(col)); } #endif /////////////////////////////////////////////////////////////////////////////// // end // template<typename T,typename C> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type> end(auto_any_t col, type2type<T,C> *, bool, mpl::true_) { return foreach::adl_end(auto_any_cast<T,C>(col)); } #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template<typename T,typename C> inline auto_any<int> end(auto_any_t col, type2type<T *,C> *, bool, mpl::true_) { return 0; // not used } #endif #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::false_>::type> end(auto_any_t col, type2type<T> *, bool, mpl::false_) { return foreach::adl_end(*auto_any_cast<T *,mpl::false_>(col)); } template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::true_>::type> end(auto_any_t col, type2type<T,const_> *, bool, mpl::false_) { return foreach::adl_end(*auto_any_cast<simple_variant<T const>,mpl::false_>(col).get()); } #else template<typename T,typename C> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type> end(auto_any_t col, type2type<T,C> *, mpl::false_, mpl::false_) // l-value { typedef BOOST_DEDUCED_TYPENAME type2type<T,C>::type type; return foreach::adl_end(*auto_any_cast<type *,mpl::false_>(col)); } template<typename T> inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T,mpl::true_>::type> end(auto_any_t col, type2type<T,const_> *, mpl::true_, mpl::false_) // r-value { return foreach::adl_end(auto_any_cast<T,mpl::true_>(col)); } #endif /////////////////////////////////////////////////////////////////////////////// // done // template<typename T,typename C> inline bool done(auto_any_t cur, auto_any_t end, type2type<T,C> *) { typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type iter_t; return auto_any_cast<iter_t,mpl::false_>(cur) == auto_any_cast<iter_t,mpl::false_>(end); } #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template<typename T,typename C> inline bool done(auto_any_t cur, auto_any_t, type2type<T *,C> *) { return ! *auto_any_cast<T *,mpl::false_>(cur); } #endif /////////////////////////////////////////////////////////////////////////////// // next // template<typename T,typename C> inline void next(auto_any_t cur, type2type<T,C> *) { typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type iter_t; ++auto_any_cast<iter_t,mpl::false_>(cur); } /////////////////////////////////////////////////////////////////////////////// // deref // template<typename T,typename C> inline BOOST_DEDUCED_TYPENAME foreach_reference<T,C>::type deref(auto_any_t cur, type2type<T,C> *) { typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T,C>::type iter_t; return *auto_any_cast<iter_t,mpl::false_>(cur); } } // namespace foreach } // namespace boost #ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION /////////////////////////////////////////////////////////////////////////////// // R-values and const R-values supported here /////////////////////////////////////////////////////////////////////////////// // A sneaky way to get the type of the collection without evaluating the expression # define BOOST_FOREACH_TYPEOF(COL) \ (true ? 0 : ::boost::foreach::encode_type(COL)) // Evaluate the collection expression, and detect if it is an l-value or and r-value # define BOOST_FOREACH_EVAL(COL) \ (true ? ::boost::foreach::rvalue_probe((COL),_foreach_rvalue) : (COL)) // The R-value/L-value-ness of the collection expression is determined dynamically # define BOOST_FOREACH_RVALUE(COL) \ _foreach_rvalue # define BOOST_FOREACH_CHEAP_COPY(COL) \ (::boost::foreach::cheap_copy(BOOST_FOREACH_TYPEOF(COL))) # define BOOST_FOREACH_NOOP(COL) \ ((void)0) #elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION) /////////////////////////////////////////////////////////////////////////////// // R-values supported here, const R-values NOT supported here /////////////////////////////////////////////////////////////////////////////// // A sneaky way to get the type of the collection without evaluating the expression # define BOOST_FOREACH_TYPEOF(COL) \ (true ? 0 : ::boost::foreach::encode_type(COL)) // Evaluate the collection expression # define BOOST_FOREACH_EVAL(COL) \ (COL) // Determine whether the collection expression is an l-value or an r-value. // NOTE: this gets the answer for const R-values wrong. # define BOOST_FOREACH_RVALUE(COL) \ (::boost::mpl::bool_<(sizeof(::boost::foreach::is_rvalue((COL),0)) \ ==sizeof(::boost::foreach::yes_type))>()) # define BOOST_FOREACH_CHEAP_COPY(COL) \ (::boost::foreach::cheap_copy(BOOST_FOREACH_TYPEOF(COL))) # define BOOST_FOREACH_NOOP(COL) \ ((void)0) #else /////////////////////////////////////////////////////////////////////////////// // R-values NOT supported here /////////////////////////////////////////////////////////////////////////////// // A sneaky way to get the type of the collection without evaluating the expression # define BOOST_FOREACH_TYPEOF(COL) \ (true ? 0 : ::boost::foreach::encode_type(COL)) // Evaluate the collection expression # define BOOST_FOREACH_EVAL(COL) \ (COL) // Can't use R-values with BOOST_FOREACH # define BOOST_FOREACH_RVALUE(COL) \ (::boost::mpl::false_()) # define BOOST_FOREACH_CHEAP_COPY(COL) \ (::boost::foreach::cheap_copy(BOOST_FOREACH_TYPEOF(COL))) // Attempt to make uses of BOOST_FOREACH with non-lvalues fail to compile # define BOOST_FOREACH_NOOP(COL) \ ((void)&(COL)) #endif #define BOOST_FOREACH_CONTAIN(COL) \ ::boost::foreach::contain( \ BOOST_FOREACH_EVAL(COL) \ , BOOST_FOREACH_RVALUE(COL) \ , BOOST_FOREACH_CHEAP_COPY(COL)) #define BOOST_FOREACH_BEGIN(COL) \ ::boost::foreach::begin( \ _foreach_col \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_RVALUE(COL) \ , BOOST_FOREACH_CHEAP_COPY(COL)) #define BOOST_FOREACH_END(COL) \ ::boost::foreach::end( \ _foreach_col \ , BOOST_FOREACH_TYPEOF(COL) \ , BOOST_FOREACH_RVALUE(COL) \ , BOOST_FOREACH_CHEAP_COPY(COL)) #define BOOST_FOREACH_DONE(COL) \ ::boost::foreach::done( \ _foreach_cur \ , _foreach_end \ , BOOST_FOREACH_TYPEOF(COL)) #define BOOST_FOREACH_NEXT(COL) \ ::boost::foreach::next( \ _foreach_cur \ , BOOST_FOREACH_TYPEOF(COL)) #define BOOST_FOREACH_DEREF(COL) \ ::boost::foreach::deref( \ _foreach_cur \ , BOOST_FOREACH_TYPEOF(COL)) /////////////////////////////////////////////////////////////////////////////// // BOOST_FOREACH // // For iterating over collections. Collections can be // arrays, null-terminated strings, or STL containers. // The loop variable can be a value or reference. For // example: // // std::list<int> int_list(/*stuff*/); // BOOST_FOREACH(int &i, int_list) // { // /* // * loop body goes here. // * i is a reference to the int in int_list. // */ // } // // Alternately, you can declare the loop variable first, // so you can access it after the loop finishes. Obviously, // if you do it this way, then the loop variable cannot be // a reference. // // int i; // BOOST_FOREACH(i, int_list) // { ... } // #define BOOST_FOREACH(VAR, COL) \ if (bool _foreach_rvalue = false) {} else \ if (::boost::foreach::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \ if (::boost::foreach::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else \ if (::boost::foreach::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else \ for (bool _foreach_continue = true; \ _foreach_continue && !BOOST_FOREACH_DONE(COL); \ _foreach_continue ? BOOST_FOREACH_NEXT(COL) : BOOST_FOREACH_NOOP(COL)) \ if (::boost::foreach::set_false(_foreach_continue)) {} else \ for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true) #endif

"Eric Niebler" <eric@boost-consulting.com> writes: <snip>
template<typename T> inline BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type adl_begin(T &t) { #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) return boost::begin(t); #else using boost::begin; typedef BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type type; return type(begin(t)); #endif }
template<typename T> inline BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type adl_end(T &t)
Either you didn't see my recent argument on boost-users that ADL is too common an acronym to be used to disambiguate such ADL customization points, or you didn't buy it, or...? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Eric Niebler" <eric@boost-consulting.com> writes:
template<typename T> inline BOOST_DEDUCED_TYPENAME range_result_iterator<T>::type adl_begin(T &t)
Either you didn't see my recent argument on boost-users that ADL is too common an acronym to be used to disambiguate such ADL customization points, or you didn't buy it, or...?
... or this is not an ADL customization point. Calls to this function are always qualified. Calls to "foreach::adl_begin(t)" are equivalent to "using boost::begin; begin(t);" modulo some compiler work-arounds. It's an implementation detail (so it really should be in a detail namespace -- I'll fix that if I'm allowed to). -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Russell Hind wrote:
Hi Eric, with the new version, I can't even get foreach.hpp to compile. I get the following error on line 308:
[C++ Error] foreach.hpp(308): E2109 Not an allowed type
This is a shot in the dark, but can you try the attached version? If this doesn't work, I'll need the help of someone familiar with this compiler.
Hi Eric, I now get an error on line 311 of foreach.hpp which is in template<typename T> struct is_range_base { BOOST_STATIC_CONSTANT(size_t, size = sizeof(boost::foreach::is_range_fun((T*)0))); BOOST_STATIC_CONSTANT(bool, value = sizeof(yes_type)==size); typedef mpl::bool_<value> type; }; The error is on the typedef mpl::bool_<value> type line. (with and without the #defines in). [C++ Error] foreach.hpp(311): E2231 Member is_range_base<T>::value cannot be used without an object [C++ Error] foreach.hpp(311): E2299 Cannot generate template specialization from 'mpl::bool_<C_>' [C++ Error] foreach.hpp(311): E2040 Declaration terminated incorrectly Cheers Russell

Russell Hind wrote:
I now get an error on line 311 of foreach.hpp which is in
template<typename T> struct is_range_base { BOOST_STATIC_CONSTANT(size_t, size = sizeof(boost::foreach::is_range_fun((T*)0))); BOOST_STATIC_CONSTANT(bool, value = sizeof(yes_type)==size); typedef mpl::bool_<value> type; };
The error is on the typedef mpl::bool_<value> type line. (with and without the #defines in).
[C++ Error] foreach.hpp(311): E2231 Member is_range_base<T>::value cannot be used without an object [C++ Error] foreach.hpp(311): E2299 Cannot generate template specialization from 'mpl::bool_<C_>' [C++ Error] foreach.hpp(311): E2040 Declaration terminated incorrectly
I'm afraid you're out of luck, for now. Without access to this compiler, or knowledge of it's quirks, there's nothing I can do. I'll gladly accept a patch if you can make it work. The first thing I would try if I were you would be to change the line: typedef mpl::bool_<value> type; to typedef mpl::bool_<is_range_base<T>::value> type; That's all I can think of right now. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
I'm afraid you're out of luck, for now. Without access to this compiler, or knowledge of it's quirks, there's nothing I can do. I'll gladly accept a patch if you can make it work. The first thing I would try if I were you would be to change the line:
typedef mpl::bool_<value> type;
to
typedef mpl::bool_<is_range_base<T>::value> type;
That's all I can think of right now.
Well we're getting somewhere. That has made foreach.hpp compile. I have to #define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION and a couple of examples I've tried now work. I haven't tried the tests (not sure how to run them easily) but this simple example compiles and runs (albeit with a load of compiler warnings about passing temporaries in to functions) BOOST_FOREACH( char ch, "Hello!" ) { std::cout << ch; } std::cout << std::endl; std::vector<int> v; BOOST_FOREACH(int& i, v) { i *= 2; std::cout << i << std::endl; } The compiler warnings are listed below. You can disable warnings temporarily on borland by #ifdef __BORLANDC__ # pragma option push -w-8032 #endif before the call and #ifdef __BORLANDC__ # pragma option pop #endif After the call. Don't know if you want to mess around with you code to do this or not. If i get the tests running, I'll report back with the details. Cheers Russell [C++] main.cpp(1): [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::mpl::false_ is_rvalue<char *>(char * &,int)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::mpl::false_ is_rvalue<char *>(char * &,int)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::mpl::false_ is_rvalue<char *>(char * &,int)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)' [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::foreach_detail_::type2type<char *,boost::mpl::false_> * encode_type<char *>(char * &)'

Russell Hind wrote:
Well we're getting somewhere. That has made foreach.hpp compile. I have to #define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION and a couple of examples I've tried now work.
Awesome! I just committed the fixes. I also committed a blunder in one of my previous fixes, which has now been fixed. I hope I didn't rock the boat.
[C++] main.cpp(1): [C++ Warning] main.cpp(14): W8032 Temporary used for parameter 1 in call to 'boost::foreach_detail_::boost::mpl::false_ is_rvalue<char *>(char * &,int)'
Doesn't look serious to me. But since the warning is coming from the cpp file and not foreach.hpp, there is nothing I can do to disable it. You'll have to do that yourself. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
I'm afraid you're out of luck, for now. Without access to this compiler, or knowledge of it's quirks, there's nothing I can do. I'll gladly accept a patch if you can make it work. The first thing I would try if I were you would be to change the line:
typedef mpl::bool_<value> type;
to
typedef mpl::bool_<is_range_base<T>::value> type;
That's all I can think of right now.
Hi Eric, I'm trying to get the tests compiling now. I run in to problems with things like this (in regress.cpp): template<typename Range> std::vector<int> to_vector_foreach_byval( Range & rng ) { std::vector<int> vect; typedef typename ::boost::range_result_iterator<Range>::type iterator; typedef typename ::boost::iterator_value<iterator>::type value; BOOST_FOREACH( value i, rng ) { vect.push_back(i); } return vect; } The two typedef lines give these errors: [C++ Error] main.cpp(110): E2437 'typename' should be followed by a qualified, dependent type name [C++ Error] main.cpp(111): E2437 'typename' should be followed by a qualified, dependent type name So quite a few of these through the regression .cpp file. Any ideas how to solve these so I can run the tests? Thanks Russell

"Russell Hind" wrote:
template<typename Range> std::vector<int> to_vector_foreach_byval( Range & rng ) { std::vector<int> vect; typedef typename ::boost::range_result_iterator<Range>::type iterator; typedef typename ::boost::iterator_value<iterator>::type value; BOOST_FOREACH( value i, rng ) { vect.push_back(i); } return vect; }
The two typedef lines give these errors:
[C++ Error] main.cpp(110): E2437 'typename' should be followed by a qualified, dependent type name [C++ Error] main.cpp(111): E2437 'typename' should be followed by a qualified, dependent type name
So quite a few of these through the regression .cpp file. Any ideas how to solve these so I can run the tests?
The :: before namespace name ::boost must be omitted. BCB doesn't like it. /Pavel

Pavel Vozenilek wrote:
"Russell Hind" wrote:
typedef typename ::boost::range_result_iterator<Range>::type iterator;
[C++ Error] main.cpp(110): E2437 'typename' should be followed by a qualified, dependent type name
The :: before namespace name ::boost must be omitted.
BCB doesn't like it. /Pavel
Thanks, fixed. -- Eric Niebler Boost Consulting www.boost-consulting.com

Russell Hind wrote:
Hi Eric, I'm trying to get the tests compiling now. I run in to problems with things like this (in regress.cpp):
template<typename Range> std::vector<int> to_vector_foreach_byval( Range & rng ) { std::vector<int> vect; typedef typename ::boost::range_result_iterator<Range>::type iterator; typedef typename ::boost::iterator_value<iterator>::type value; BOOST_FOREACH( value i, rng ) { vect.push_back(i); } return vect; }
The two typedef lines give these errors:
[C++ Error] main.cpp(110): E2437 'typename' should be followed by a qualified, dependent type name [C++ Error] main.cpp(111): E2437 'typename' should be followed by a qualified, dependent type name
Could you try replacing "typename" with "BOOST_DEDUCED_TYPENAME"? (Also, I think it's a good idea to take this discussion offlist to keep traffic down until we get the kinks worked out. Feel free to reply to me directly.) -- Eric Niebler Boost Consulting www.boost-consulting.com

On Thu, 10 Mar 2005 17:44:34 +0000 Russell Hind <rh_gmane@mac.com> wrote:
template<typename Range> std::vector<int> to_vector_foreach_byval( Range & rng ) { std::vector<int> vect; typedef typename ::boost::range_result_iterator<Range>::type iterator; typedef typename ::boost::iterator_value<iterator>::type value; BOOST_FOREACH( value i, rng ) { vect.push_back(i); } return vect; }
The two typedef lines give these errors:
[C++ Error] main.cpp(110): E2437 'typename' should be followed by a qualified, dependent type name [C++ Error] main.cpp(111): E2437 'typename' should be followed by a qualified, dependent type name
So quite a few of these through the regression .cpp file. Any ideas how to solve these so I can run the tests?
replace typename with BOOST_DEDUCED_TYPENAME and see if that works. If not, then you may need a similar workaround that is used elsewhere... template<typename Range> std::vector<int> to_vector_foreach_byval( Range & rng ) { #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x564) # define BOOST_typename #else # define BOOST_typename BOOST_DEDUCED_TYPENAME #endif std::vector<int> vect; typedef BOOST_typename ::boost::range_result_iterator<Range>::type iterator; typedef BOOST_typename ::boost::iterator_value<iterator>::type value; BOOST_FOREACH( value i, rng ) { vect.push_back(i); } return vect; #undef BOOST_typename }

Eric Niebler wrote:
I just uploaded to the Boost Sandbox File Vault a new and improved version of BOOST_FOREACH. Since much of the code is new, I removed many of the old work-arounds, so things are likely to break until the dust settles. I have verified it works on VC6+ and gcc 3.3.3.
I would be especially interested in seeing results from BCC, EDG-based compilers, and GCC 2.9x. You can find foreach.zip at:
http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
There is a simple regression test there and a Jamfile. If it doesn't compile, try defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION. If it still doesn't compiler, try defining BOOST_FOREACH_NO_RVALUE_DETECTION. Let me know the compiler version, and which macros you needed to define to get it to work.
gcc 2.95.3: without #defines: foreach.hpp:27: Invalid token in expression with NO_CONST_RVALUE_DETECTION: same error with NO_RVALUE_DETECTION: same error icc 8.1: without #defines: ../../../boost/foreach.hpp(241): error: a new-initializer may not be specified for an array ::new(data.address()) T(t); ^ detected during: instantiation of "boost::foreach::simple_variant<T>::simple_variant(const T &) [with T=const int [5]]" at line 349 instantiation of "boost::foreach::auto_any<boost::foreach::simple_variant<const T>> boost::foreach::contain(const T &, const bool &, boost::mpl::false_) [with T=int [5]]" at line 88 of "regress.cpp" instantiation of "std::vector<int, std::allocator<int>> to_vector_foreach_byval(Range &) [with Range=const int [5]]" ../../../boost/foreach.hpp(248): error: a new-initializer may not be specified for an array ::new(data.address()) T(*that.get()); ^ detected during: instantiation of "boost::foreach::simple_variant<T>::simple_variant(const boost::foreach::simple_variant<T> &) [with T=const int [5]]" at line 113 instantiation of "boost::foreach::auto_any<T>::auto_any(const T &) [with T=boost::foreach::simple_variant<const int [5]>]" at line 349 instantiation of "boost::foreach::auto_any<boost::foreach::simple_variant<const T>> boost::foreach::contain(const T &, const bool &, boost::mpl::false_) [with T=int [5]]" at line 88 of "regress.cpp" instantiation of "std::vector<int, std::allocator<int>> to_vector_foreach_byval(Range &) [with Range=const int [5]]" icc 8.1 with NO_CONST_RVALUE_DETECTION: works icc 8.1 with NO_RVALUE_DETECTION: works gcc 3.4.3, without #defines: ../../../boost/foreach.hpp: In copy constructor `boost::foreach::simple_variant<T>::simple_variant(const boost::foreach::simple_variant<T>&) [with T = const int[5]]': regress.cpp:88: instantiated from `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = const int[5]]' regress.cpp:138: instantiated from here ../../../boost/foreach.hpp:248: error: ISO C++ forbids initialization in array new ../../../boost/foreach.hpp: In constructor `boost::foreach::simple_variant<T>::simple_variant(const T&) [with T = const int[5]]': ../../../boost/foreach.hpp:349: instantiated from `boost::foreach::auto_any<boost::foreach::simple_variant<const T> > boost::foreach::contain(const T&, const bool&, mpl_::false_) [with T = int[5]]' regress.cpp:88: instantiated from `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = const int[5]]' regress.cpp:138: instantiated from here ../../../boost/foreach.hpp:241: error: ISO C++ forbids initialization in array new gcc 3.4.3, with NO_CONST_RVALUE_DETECTION: works gcc 3.4.3, with NO_RVALUE_DETECTION: works gcc-4, without #defines: ../../../boost/foreach.hpp: In copy constructor 'boost::foreach::simple_variant<T>::simple_variant(const boost::foreach::simple_variant<T>&) [with T = const int [5]]': regress.cpp:88: instantiated from 'std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = const int [5]]' regress.cpp:138: instantiated from here ../../../boost/foreach.hpp:248: error: ISO C++ forbids initialization in array new ../../../boost/foreach.hpp: In constructor 'boost::foreach::simple_variant<T>::simple_variant(const T&) [with T = const int [5]]': ../../../boost/foreach.hpp:349: instantiated from 'boost::foreach::auto_any<boost::foreach::simple_variant<const T> > boost::foreach::contain(const T&, const bool&, mpl_::false_) [with T = int [5]]' regress.cpp:88: instantiated from 'std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = const int [5]]' regress.cpp:138: instantiated from here ../../../boost/foreach.hpp:241: error: ISO C++ forbids initialization in array new gcc 4, with NO_CONST_RVALUE_DETECTION: works gcc 4, with NO_RVALUE_DETECTION: works HTH, m

Thanks, Martin! New version posted to the file vault: http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler Comments inline: Martin Wille wrote:
gcc 2.95.3:
without #defines: foreach.hpp:27: Invalid token in expression with NO_CONST_RVALUE_DETECTION: same error with NO_RVALUE_DETECTION: same error
I installed gcc 2.95 and didn't get this error. But I got a host of others, which are fixed. (Well, sort of. BOOST_FOREACH works in some constructs but not in others.)
icc 8.1:
without #defines: ../../../boost/foreach.hpp(241): error: a new-initializer may not be specified for an array ::new(data.address()) T(t); ^
Yup, array handling was broken. Should be fixed now (but I don't have icc to test).
gcc 3.4.3, without #defines: ../../../boost/foreach.hpp:248: error: ISO C++ forbids initialization in array new
Same problem as above, I think. I have verified the fix with gcc 3.4.
gcc-4, without #defines: ../../../boost/foreach.hpp:248: error: ISO C++ forbids initialization in array new
Probably fixed, but I don't have gcc-4 to test. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Thanks, Martin! New version posted to the file vault:
http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
Comments inline:
Martin Wille wrote:
gcc 2.95.3:
without #defines: foreach.hpp:27: Invalid token in expression with NO_CONST_RVALUE_DETECTION: same error with NO_RVALUE_DETECTION: same error
I installed gcc 2.95 and didn't get this error.
This was caused by escaped cr-lf line endings in macro definitions not being treated correctly by gcc 2.95.3. I now get these errors for gcc 2.95.3: regress.cpp: In function `class vector<int,allocator<int> > to_vector_foreach_byval<int[5]>(int (&)[5])': regress.cpp:132: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:132: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:132: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp: In function `class vector<int,allocator<int> > to_vector_foreach_byval<char *>(char *&)': regress.cpp:133: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:133: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:133: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp: In function `class vector<int,allocator<int> > to_vector_foreach_byval<list<int,allocator<int> >
(list<int,allocator<int> > &)': regress.cpp:134: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:134: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:134: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp: In function `class vector<int,allocator<int> > to_vector_foreach_byval<pair<boost::counting_iterator<int,boost::use_default,boost::use_default>,boost::counting_iterator<int,boost::use_default,boost::use_default>
(pair<boost::counting_iterator<int,boost::use_default,boost::use_default>,boost::counting_iterator<int,boost::use_default,boost::use_default> &)': regress.cpp:135: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:135: instantiated from here regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !=' regress.cpp:135: instantiated from here (+ a lot more messages of the same type)
icc 8.1 works now. gcc 3.3.5 works. gcc 3.4.3 works. gcc-4 without #defines: /boost/head-regression/boost/boost/iterator/counting_iterator.hpp:32: error: '(bool)(boost::is_integral<char>::value)' is not a valid template argument for type 'bool' because it is a non-constant expression ../../../boost/foreach.hpp:281: error: '(size_t)((-1))' is not a valid template argument for type 'unsigned int' because it is a non-constant expression ../../../boost/foreach.hpp: In constructor 'boost::foreach_detail_::simple_variant<T>::simple_variant(T*)': ../../../boost/foreach.hpp:245: error: request for member 'address' in '((boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' ../../../boost/foreach.hpp: In constructor 'boost::foreach_detail_::simple_variant<T>::simple_variant(const T&)': ../../../boost/foreach.hpp:251: error: request for member 'address' in '((boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' ../../../boost/foreach.hpp: In copy constructor 'boost::foreach_detail_::simple_variant<T>::simple_variant(const boost::foreach_detail_::simple_variant<T>&)': ../../../boost/foreach.hpp:258: error: request for member 'address' in '((boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' ../../../boost/foreach.hpp:260: error: request for member 'address' in '((boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' ../../../boost/foreach.hpp: In member function 'T* boost::foreach_detail_::simple_variant<T>::get() const': ../../../boost/foreach.hpp:272: error: request for member 'address' in '((const boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' ../../../boost/foreach.hpp:274: error: request for member 'address' in '((const boost::foreach_detail_::simple_variant<T>*)this)->boost::foreach_detail_::simple_variant<T>::data', which is of non-class type 'int' gcc-4 with BOOST_FOREACH_NO_RVALUE_DETECTION or with BOOST_FOREACH_NO_CONST_RVALUE_DETECTION: /boost/head-regression/boost/boost/iterator/counting_iterator.hpp:32: error: '(bool)(boost::is_integral<char>::value)' is not a valid template argument for type 'bool' because it is a non-constant expression. gcc 3.2.3 without defines: regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = int[5]]': regress.cpp:132: instantiated from here regress.cpp:88: no match for `bool ? boost::foreach_detail_::rvalue_probe : int[5]' operator regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = const int[5]]': regress.cpp:138: instantiated from here regress.cpp:88: no match for `bool ? boost::foreach_detail_::rvalue_probe : const int[5]' operator regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byref(Range&) [with Range = int[5]]': regress.cpp:144: instantiated from here regress.cpp:104: no match for `bool ? boost::foreach_detail_::rvalue_probe : int[5]' operator regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byref(Range&) [with Range = const int[5]]': regress.cpp:150: instantiated from here regress.cpp:104: no match for `bool ? boost::foreach_detail_::rvalue_probe : const int[5]' operator regress.cpp: In function `void mutate_foreach_byref(Range&) [with Range = int[5]]': regress.cpp:156: instantiated from here regress.cpp:119: no match for `bool ? boost::foreach_detail_::rvalue_probe : int[5]' operator Regards, m

Would it be worth writing a typeof based version of FOREACH for gcc? It would probably work better on the older versions.

Daniel James wrote:
Would it be worth writing a typeof based version of FOREACH for gcc? It would probably work better on the older versions.
Probably not. Much of the trouble is from the rvalue detection stuff, and my understanding of GCC's typeof is that it strips top level references. Besides, BOOST_FOREACH has well-defined customization points. To keep the customization points consistent across typeof and non-typeof compilers, you would first need to implement Boost.Range with typeof, and then build BOOST_FOREACH on top of that. -- Eric Niebler Boost Consulting www.boost-consulting.com

Inline ... Martin Wille wrote:
I now get these errors for gcc 2.95.3:
regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !='
As I mentioned, gcc 2.95 accepts BOOST_FOREACH in some onstructs but not others. In particular, the compiler chokes when BOOST_FOREACH is in a function template, like above. Simpler uses are fine. I'd gladly accept a patch, but I'm not inclined to waste much more of my time on this ancient compiler.
gcc-4 without #defines:
/boost/head-regression/boost/boost/iterator/counting_iterator.hpp:32: error: '(bool)(boost::is_integral<char>::value)' is not a valid template argument for type 'bool' because it is a non-constant expression ../../../boost/foreach.hpp:281: error: '(size_t)((-1))' is not a valid template argument for type 'unsigned int' because it is a non-constant expression
Whoa. This is some pretty basic, legal C++ that gcc-4 is choking on. Has gcc-4 been released yet? If not, I'm going to wait for it to stabilize a bit.
gcc 3.2.3 without defines:
regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = int[5]]': regress.cpp:132: instantiated from here regress.cpp:88: no match for `bool ? boost::foreach_detail_::rvalue_probe : int[5]' operator
I'm guessing that defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION makes this go away? That's probably the right fix. It looks like gcc-3.2 is choking on the fancy rvalue detection stuff. I'll fix this. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
Inline ...
Martin Wille wrote:
I now get these errors for gcc 2.95.3:
regress.cpp:88: invalid operands `const boost::foreach_detail_::auto_any_base &' and `int' to binary `operator !='
As I mentioned, gcc 2.95 accepts BOOST_FOREACH in some onstructs but not others. In particular, the compiler chokes when BOOST_FOREACH is in a function template, like above. Simpler uses are fine. I'd gladly accept a patch, but I'm not inclined to waste much more of my time on this ancient compiler.
I wouldn't have supported it in the first place :)
gcc-4 without #defines:
/boost/head-regression/boost/boost/iterator/counting_iterator.hpp:32: error: '(bool)(boost::is_integral<char>::value)' is not a valid template argument for type 'bool' because it is a non-constant expression ../../../boost/foreach.hpp:281: error: '(size_t)((-1))' is not a valid template argument for type 'unsigned int' because it is a non-constant expression
Whoa. This is some pretty basic, legal C++ that gcc-4 is choking on. Has gcc-4 been released yet? If not, I'm going to wait for it to stabilize a bit.
No it hasn't been released, yet.
gcc 3.2.3 without defines:
regress.cpp: In function `std::vector<int, std::allocator<int> > to_vector_foreach_byval(Range&) [with Range = int[5]]': regress.cpp:132: instantiated from here regress.cpp:88: no match for `bool ? boost::foreach_detail_::rvalue_probe : int[5]' operator
I'm guessing that defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION makes this go away? That's probably the right fix. It looks like gcc-3.2 is choking on the fancy rvalue detection stuff. I'll fix this.
Well, I'd consider gcc 3.2 not worth supporting. However, since you asked for gcc 2.95 in your first message, I thought you might be interested in the results for gcc 3.2, too. Yes, the error goes away with BOOST_FOREACH_NO_CONST_RVALUE_DETECTION. (The very same applies to gcc 3.1 and gcc 3.0.4) Regards, m

"Eric Niebler" <eric@boost-consulting.com> writes:
Russell Hind wrote:
Has anyone tried BOOST_FOREACH with bcc32-5.6.4? I've just tried the example
<snip>
I just uploaded to the Boost Sandbox File Vault a new and improved version of BOOST_FOREACH. Since much of the code is new, I removed many of the old work-arounds, so things are likely to break until the dust settles. I have verified it works on VC6+ and gcc 3.3.3.
I would be especially interested in seeing results from BCC, EDG-based compilers, and GCC 2.9x. You can find foreach.zip at:
http://tinyurl.com/5qhj8 http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
There is a simple regression test there and a Jamfile. If it doesn't compile, try defining BOOST_FOREACH_NO_CONST_RVALUE_DETECTION. If it still doesn't compiler, try defining BOOST_FOREACH_NO_RVALUE_DETECTION. Let me know the compiler version, and which macros you needed to define to get it to work.
Thanks!
Say, is this component in the review queue? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Eric Niebler" <eric@boost-consulting.com> writes:
I just uploaded to the Boost Sandbox File Vault a new and improved version of BOOST_FOREACH.
Say, is this component in the review queue?
Yes. Did I do wrong? The review hasn't started yet, and won't for a while judging from the depth of the queue. Can people not update their libraries while waiting for the review to start? -- Eric Niebler Boost Consulting www.boost-consulting.com

"Eric Niebler" <eric@boost-consulting.com> wrote
David Abrahams wrote:
Say, is this component in the review queue?
Yes. Did I do wrong? The review hasn't started yet, and won't for a while judging from the depth of the queue. Can people not update their libraries while waiting for the review to start?
The Boost web site says "A proposed library should remain stable _during the review period_". I don't think being in the review queue can be qualified as the review period... Also it says: "The submission file should contain material as if on the boost.org web site. The closer the submission file mirrors the final directory structure and format of the web site, the better". This means that people who place there code inside boost namespace, call their libraries Boost.Whatever, etc., technically do everything as required. And people who place any kind of disclamers in their code/docs -- don't. I don't mean all this is the ideal procedure, and of course it can be changed. But I do think that while the web site stays as it is now, people should not be expected to do anything differently. Regards, Arkadiy

"Arkadiy Vertleyb" <vertleyb@hotmail.com> writes:
"Eric Niebler" <eric@boost-consulting.com> wrote
David Abrahams wrote:
Say, is this component in the review queue?
Yes.
Thanks.
Did I do wrong? The review hasn't started yet, and won't for a while judging from the depth of the queue. Can people not update their libraries while waiting for the review to start?
The Boost web site says "A proposed library should remain stable _during the review period_". I don't think being in the review queue can be qualified as the review period...
I wasn't chiding anyone, I was just asking a question! Thanks again. trying-to-avoid-another-federal-case-ly y'rs ;-) -- Dave Abrahams Boost Consulting www.boost-consulting.com

Is it possible to use the BOOST_FOREACH technology to create something that work with objects where end is the default constructor? example boost::filesystem for (directory_iterator itr("C:\\"); itr != directory_iterator(); ++itr) .. BOOST_FOREACH_2(directory_iterator itr("C:\\"))

Martin wrote:
Is it possible to use the BOOST_FOREACH technology to create something that work with objects where end is the default constructor?
example boost::filesystem
for (directory_iterator itr("C:\\"); itr != directory_iterator(); ++itr) ..
BOOST_FOREACH_2(directory_iterator itr("C:\\"))
Possible? Yes, but my gut tells me not to. BOOST_FOREACH works with ranges, not iterators, and i don't want to create confusion about that. FWIW, you can iterate over a directory like: directory_iterator begin("C:\\"), end; BOOST_FOREACH(path p, std::make_pair(begin,end)) { } -- Eric Niebler Boost Consulting www.boost-consulting.com
participants (10)
-
Arkadiy Vertleyb
-
Daniel James
-
David Abrahams
-
Eric Niebler
-
Gennadiy Rozental
-
Jody Hagins
-
Martin
-
Martin Wille
-
Pavel Vozenilek
-
Russell Hind