
You can help improve Boost.Foreach and Boost.Typeof for your favorite compiler! Read on. Eric Niebler wrote:
Thorsten Ottosen wrote:
Now it works on vc7.1 too.
getting this to work with vc7.1 is a major advance. Thanks.
I am now using the compile-time-const-rvalue-detection trick in the new-and-improved BOOST_FOREACH. For the first time, it's passing its tests at 100% for VC7.1 and VC8. Also, const rvalues are being detected on gcc 3.4+ with zero runtime overhead. Very nice! OK, now here's a simple thing anybody can do to improve Foreach and Typeof. Try compiling the attached file on your favorite compiler and report the results. I already know it works for VC7.1+ and gcc 3.4+. Everything else is up for grabs. Extra credit #1: If it doesn't compile for you, patch it so it does. :-) Extra credit #2: Find a formulation that is 100% standard compliant. Back up your claim by citing references from the standard. :-))) -- Eric Niebler Boost Consulting www.boost-consulting.com // Copyright 2005 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) #include <boost/config.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/logical.hpp> #include <boost/type_traits/is_array.hpp> namespace impl_ { typedef char yes_type; typedef char (&no_type)[2]; yes_type is_true(boost::mpl::true_ *); no_type is_true(boost::mpl::false_ *); #define PROTECT(expr) \ (static_cast<boost::mpl::bool_<1 == sizeof(impl_::is_true(expr))> *>(0)) template<typename Bool1, typename Bool2> inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; } template<typename Bool> inline boost::mpl::not_<Bool> *not_(Bool *) { return 0; } template<typename T> inline boost::mpl::false_ *is_rvalue(T &, int) { return 0; } template<typename T> inline boost::mpl::true_ *is_rvalue(T const &, ...) { return 0; } template<typename T> inline boost::is_array<T> *is_array(T const &) { return 0; } template<typename T> struct rvalue_probe { // can't ever return an array by value typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<boost::is_array<T>, int, T>::type value_type; operator value_type(); operator T &() const; }; template<typename T> rvalue_probe<T> const make_probe(T const &t); } // namespace impl_ #define IS_RVALUE_IMPL(COL) \ impl_::and_(impl_::not_(impl_::is_array(COL)) \ , PROTECT(impl_::is_rvalue((true ? impl_::make_probe(COL) : (COL)), 0))) #define IS_RVALUE(COL) (1==sizeof(impl_::is_true(IS_RVALUE_IMPL(COL)))) ///////////////////////////////////////////////////////////////////////// // test begins here // struct foo { foo() {} }; foo const make_foo() { return foo(); } int main() { int i = 0; int const ci = 0; char test1[ IS_RVALUE(1) ]; char test2[ IS_RVALUE(int()) ]; char test3[ ! IS_RVALUE(i) ]; char test4[ ! IS_RVALUE(ci) ]; foo f; foo const cf; typedef foo const cfoo; char test5[ IS_RVALUE(foo()) ]; char test6[ IS_RVALUE(cfoo()) ]; char test7[ IS_RVALUE(make_foo()) ]; char test8[ ! IS_RVALUE(f) ]; char test9[ ! IS_RVALUE(cf) ]; int rgi[2] = {1,2}; int const crgi[2] = {1,2}; char test10[ ! IS_RVALUE(rgi) ]; char test11[ ! IS_RVALUE(crgi) ]; return 0; }