分类:
2008-10-13 16:12:30
功能示例:
#include <iostream>
#include <boost/foreach.hpp>
int main()
{
BOOST_FOREACH( char ch, "Hello, world!" )
{
std::cout << ch;
}
return 0;
}
std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
// do something with i
}
std::deque<int> deque_int( /*...*/ );
int i = 0;
BOOST_FOREACH( i, deque_int )
{
if(i==0) return;
if(i==1) continue;
if(i==2) break;
}
extern std::vector<float> get_vector_float();
BOOST_FOREACH( float f, get_vector_float() )
{
// Note: get_vector_float() will be called exactly once
}
关文件如下:需要boost支持
///////////////////////////////////////////////////////////////////////////////
// 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
// )
//
#ifndef BOOST_FOREACH
#include
#include
#include
#include
// 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) \
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))
# 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)) \
|| BOOST_WORKAROUND(__GNUC__, < 3) \
|| (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 2))
# define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
# include
# include
# include
# include
#endif
namespace boost
{
// forward declarations for iterator_range
template
class iterator_range;
// forward declarations for sub_range
template
class sub_range;
namespace foreach
{
///////////////////////////////////////////////////////////////////////////////
// in_range
//
template
inline std::pair
{
return std::make_pair(begin, end);
}
} // namespace foreach
namespace foreach_detail_
{
///////////////////////////////////////////////////////////////////////////////
// adl_begin/adl_end
//
template
inline BOOST_DEDUCED_TYPENAME range_result_iterator
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
|| BOOST_WORKAROUND(__GNUC__, < 3)
return boost::begin(t);
#else
using boost::begin;
typedef BOOST_DEDUCED_TYPENAME range_result_iterator
return type(begin(t));
#endif
}
template
inline BOOST_DEDUCED_TYPENAME range_result_iterator
{
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
|| BOOST_WORKAROUND(__GNUC__, < 3)
return boost::end(t);
#else
using boost::end;
typedef BOOST_DEDUCED_TYPENAME range_result_iterator
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
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
inline BOOST_DEDUCED_TYPENAME boost::mpl::if_
{
return static_cast
}
typedef boost::mpl::true_ const_;
///////////////////////////////////////////////////////////////////////////////
// type2type
//
template
struct type2type
: boost::mpl::if_
{
};
template
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 boost::mpl::eval_if<
C
, range_const_iterator
, range_iterator
>::type type;
#else
typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
C
, range_result_iterator
, range_result_iterator
>::type type;
#endif
};
template
struct foreach_reference
: iterator_reference
{
};
///////////////////////////////////////////////////////////////////////////////
// encode_type
//
template
inline type2type
{
return 0;
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template
inline type2type
{
return 0;
}
#endif
#ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
///////////////////////////////////////////////////////////////////////////////
// rvalue_probe
//
struct rvalue_probe
{
template
rvalue_probe(T const &t, bool &b)
: ptemp(const_cast
, rvalue(b)
{
}
template
operator U()
{
rvalue = true;
return *static_cast(ptemp);
}
template
operator V &() const
{
return *static_cast
}
void *ptemp;
bool &rvalue;
};
///////////////////////////////////////////////////////////////////////////////
// simple_variant
// holds either a T or a T*
template
struct simple_variant
{
simple_variant(T *t)
: rvalue(false)
{
*static_cast
}
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
}
~simple_variant()
{
if(rvalue)
get()->~T();
}
T *get() const
{
if(rvalue)
return static_cast
else
return *static_cast
}
private:
enum { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
simple_variant &operator =(simple_variant const &);
bool const rvalue;
mutable aligned_storage
};
#elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION)
///////////////////////////////////////////////////////////////////////////////
// is_rvalue
//
template
inline mpl::false_ *is_rvalue(T &, int)
{
return 0;
}
template
inline mpl::true_ *is_rvalue(T const &, ...)
{
return 0;
}
#endif // BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
///////////////////////////////////////////////////////////////////////////////
// set_false
//
inline bool set_false(bool &b)
{
return b = false;
}
///////////////////////////////////////////////////////////////////////////////
// to_ptr
//
template
inline T *to_ptr(T const &t) { return 0; }
// Borland needs a little extra help with arrays
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template
inline T (*to_ptr(T (&t)[N]))[N] { return 0; }
#endif
///////////////////////////////////////////////////////////////////////////////
// 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.
inline mpl::false_ *cheap_copy(...) { return 0; }
template
inline mpl::true_ *cheap_copy(std::pair
template
inline mpl::true_ *cheap_copy(iterator_range
template
inline mpl::true_ *cheap_copy(sub_range
template
inline mpl::true_ *cheap_copy(T **) { return 0; }
template
inline mpl::false_ *cheap_copy(T (*)[N]) { return 0; }
///////////////////////////////////////////////////////////////////////////////
// derefof
//
template
inline T &derefof(T *t)
{
// This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N],
// then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue.
return reinterpret_cast
*const_cast
reinterpret_cast
)
);
}
///////////////////////////////////////////////////////////////////////////////
// contain
//
template
inline auto_any
{
return t;
}
#ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
template
inline auto_any
{
return boost::addressof(t);
}
template
inline BOOST_DEDUCED_TYPENAME disable_if<
is_array
, auto_any
>::type
contain(T const &t, bool *rvalue, boost::mpl::false_ *)
{
return *rvalue ? simple_variant
}
#else
template
inline auto_any
{
return boost::addressof(t);
}
template
inline auto_any
{
return t;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// begin
//
template
inline auto_any
begin(auto_any_t col, type2type
{
return foreach_detail_::adl_begin(auto_any_cast
}
#ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
template
inline auto_any
begin(auto_any_t col, type2type
{
typedef BOOST_DEDUCED_TYPENAME type2type
return foreach_detail_::adl_begin(derefof(auto_any_cast
}
template
inline BOOST_DEDUCED_TYPENAME disable_if<
is_array
, auto_any
>::type
begin(auto_any_t col, type2type
{
return foreach_detail_::adl_begin(*auto_any_cast
}
#else
template
inline auto_any
begin(auto_any_t col, type2type
{
typedef BOOST_DEDUCED_TYPENAME type2type
typedef BOOST_DEDUCED_TYPENAME foreach_iterator
return iterator(foreach_detail_::adl_begin(derefof(auto_any_cast
}
template
inline auto_any
begin(auto_any_t col, type2type
{
return foreach_detail_::adl_begin(auto_any_cast
}
#endif
///////////////////////////////////////////////////////////////////////////////
// end
//
template
inline auto_any
end(auto_any_t col, type2type
{
return foreach_detail_::adl_end(auto_any_cast
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template
inline auto_any
end(auto_any_t col, type2type
{
return 0; // not used
}
#endif
#ifndef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
template
inline auto_any
end(auto_any_t col, type2type
{
typedef BOOST_DEDUCED_TYPENAME type2type
return foreach_detail_::adl_end(derefof(auto_any_cast
}
template
inline BOOST_DEDUCED_TYPENAME disable_if<
is_array
, auto_any
>::type
end(auto_any_t col, type2type
{
return foreach_detail_::adl_end(*auto_any_cast
}
#else
template
inline auto_any
end(auto_any_t col, type2type
{
typedef BOOST_DEDUCED_TYPENAME type2type
typedef BOOST_DEDUCED_TYPENAME foreach_iterator
return iterator(foreach_detail_::adl_end(derefof(auto_any_cast
}
template
inline auto_any
end(auto_any_t col, type2type
{
return foreach_detail_::adl_end(auto_any_cast
}
#endif
///////////////////////////////////////////////////////////////////////////////
// done
//
template
inline bool done(auto_any_t cur, auto_any_t end, type2type
{
typedef BOOST_DEDUCED_TYPENAME foreach_iterator
return auto_any_cast
}
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template
inline bool done(auto_any_t cur, auto_any_t, type2type
{
return ! *auto_any_cast
}
#endif
///////////////////////////////////////////////////////////////////////////////
// next
//
template
inline void next(auto_any_t cur, type2type
{
typedef BOOST_DEDUCED_TYPENAME foreach_iterator
++auto_any_cast
}
///////////////////////////////////////////////////////////////////////////////
// deref
//
template
inline BOOST_DEDUCED_TYPENAME foreach_reference
deref(auto_any_t cur, type2type
{
typedef BOOST_DEDUCED_TYPENAME foreach_iterator
return *auto_any_cast
}
} // namespace foreach_detail_
} // 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_detail_::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_detail_::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) \
(true ? 0 : boost::foreach_detail_::cheap_copy(boost::foreach_detail_::to_ptr(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_detail_::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) \
(true ? 0 : boost::foreach_detail_::is_rvalue((COL), 0))
# define BOOST_FOREACH_CHEAP_COPY(COL) \
(true ? 0 : boost::foreach_detail_::cheap_copy(boost::foreach_detail_::to_ptr(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_detail_::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) \
(static_cast
# define BOOST_FOREACH_CHEAP_COPY(COL) \
(true ? 0 : boost::foreach_detail_::cheap_copy(boost::foreach_detail_::to_ptr(COL)))
// Attempt to make uses of BOOST_FOREACH with non-lvalues fail to compile
// BUGBUG but cheap-to-copy containers *would* be handled correctly. Hrm.
# define BOOST_FOREACH_NOOP(COL) \
((void)&(COL))
#endif
#define BOOST_FOREACH_CONTAIN(COL) \
boost::foreach_detail_::contain( \
BOOST_FOREACH_EVAL(COL) \
, BOOST_FOREACH_RVALUE(COL) \
, BOOST_FOREACH_CHEAP_COPY(COL))
#define BOOST_FOREACH_BEGIN(COL) \
boost::foreach_detail_::begin( \
_foreach_col \
, BOOST_FOREACH_TYPEOF(COL) \
, BOOST_FOREACH_RVALUE(COL) \
, BOOST_FOREACH_CHEAP_COPY(COL))
#define BOOST_FOREACH_END(COL) \
boost::foreach_detail_::end( \
_foreach_col \
, BOOST_FOREACH_TYPEOF(COL) \
, BOOST_FOREACH_RVALUE(COL) \
, BOOST_FOREACH_CHEAP_COPY(COL))
#define BOOST_FOREACH_DONE(COL) \
boost::foreach_detail_::done( \
_foreach_cur \
, _foreach_end \
, BOOST_FOREACH_TYPEOF(COL))
#define BOOST_FOREACH_NEXT(COL) \
boost::foreach_detail_::next( \
_foreach_cur \
, BOOST_FOREACH_TYPEOF(COL))
#define BOOST_FOREACH_DEREF(COL) \
boost::foreach_detail_::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
// 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_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \
if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else \
if (boost::foreach_detail_::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_detail_::set_false(_foreach_continue)) {} else \
for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
#endif