|
Boost : |
From: Eric Niebler (eric_at_[hidden])
Date: 2005-12-28 14:34:32
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;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk