Boost logo

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