mirror of
https://github.com/boostorg/foreach.git
synced 2026-02-02 21:02:11 +00:00
latest BOOST_FOREACH
[SVN r46538]
This commit is contained in:
11
doc/foreach.qbk
Executable file → Normal file
11
doc/foreach.qbk
Executable file → Normal file
@@ -162,6 +162,14 @@ Iterate over an expression that returns a sequence by value (i.e. an rvalue):
|
||||
// Note: get_vector_float() will be called exactly once
|
||||
}
|
||||
|
||||
Iterate in reverse:
|
||||
|
||||
std::list<int> list_int( /*...*/ );
|
||||
BOOST_REVERSE_FOREACH( int i, list_int )
|
||||
{
|
||||
// do something with i
|
||||
}
|
||||
|
||||
Iterating over rvalues doesn't work on some older compilers. Check the
|
||||
[link foreach.portability Portability] section to see whether your
|
||||
compiler supports this.
|
||||
@@ -174,7 +182,8 @@ the [@http://www.boost.org/more/lib_guide.htm Boost Naming Convention]. That
|
||||
doesn't mean you're stuck with it, though. If you would like to use a different
|
||||
identifier (`foreach`, perhaps), you can simply do:
|
||||
|
||||
#define foreach BOOST_FOREACH
|
||||
#define foreach BOOST_FOREACH
|
||||
#define reverse_foreach BOOST_REVERSE_FOREACH
|
||||
|
||||
Only do this if you are sure that the identifier you choose will not cause
|
||||
name conflicts in your code.
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \
|
||||
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \
|
||||
|| BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) \
|
||||
|| BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
|
||||
|| BOOST_WORKAROUND(__DECCXX_VER, <= 60590042)
|
||||
# define BOOST_FOREACH_NO_RVALUE_DETECTION
|
||||
# endif
|
||||
// Some compilers do not correctly implement the lvalue/rvalue conversion
|
||||
@@ -69,7 +69,10 @@
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/reverse_iterator.hpp>
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_abstract.hpp>
|
||||
@@ -202,15 +205,6 @@ namespace foreach_detail_
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define some utilities for assessing the properties of expressions
|
||||
//
|
||||
typedef char yes_type;
|
||||
typedef char (&no_type)[2];
|
||||
yes_type is_true(boost::mpl::true_ *);
|
||||
no_type is_true(boost::mpl::false_ *);
|
||||
|
||||
// Extracts the desired property from the expression without evaluating it
|
||||
#define BOOST_FOREACH_PROTECT(expr) \
|
||||
(static_cast<boost::mpl::bool_<1 == sizeof(boost::foreach_detail_::is_true(expr))> *>(0))
|
||||
|
||||
template<typename Bool1, typename Bool2>
|
||||
inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; }
|
||||
|
||||
@@ -368,6 +362,37 @@ struct foreach_iterator
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename C = boost::mpl::false_>
|
||||
struct foreach_reverse_iterator
|
||||
{
|
||||
// **** READ THIS IF YOUR COMPILE BREAKS HERE ****
|
||||
//
|
||||
// There is an ambiguity about how to iterate over arrays of char and wchar_t.
|
||||
// Should the last array element be treated as a null terminator to be skipped, or
|
||||
// is it just like any other element in the array? To fix the problem, you must
|
||||
// say which behavior you want.
|
||||
//
|
||||
// To treat the container as a null-terminated string, merely cast it to a
|
||||
// char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ...
|
||||
//
|
||||
// To treat the container as an array, use boost::as_array() in <boost/range/as_array.hpp>,
|
||||
// as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ...
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
BOOST_MPL_ASSERT_MSG( (!is_char_array<T>::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) );
|
||||
#endif
|
||||
|
||||
// If the type is a pointer to a null terminated string (as opposed
|
||||
// to an array type), there is no ambiguity.
|
||||
typedef BOOST_DEDUCED_TYPENAME wrap_cstr<T>::type container;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
|
||||
C
|
||||
, range_reverse_iterator<container const>
|
||||
, range_reverse_iterator<container>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<typename T, typename C = boost::mpl::false_>
|
||||
struct foreach_reference
|
||||
: iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
|
||||
@@ -386,7 +411,11 @@ inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_ *) { retur
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// set_false
|
||||
//
|
||||
inline bool set_false(bool &b) { return b = false; }
|
||||
inline bool set_false(bool &b)
|
||||
{
|
||||
b = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// to_ptr
|
||||
@@ -441,17 +470,20 @@ struct rvalue_probe
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
|
||||
boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T
|
||||
>::type value_type;
|
||||
operator value_type();
|
||||
operator T &() const;
|
||||
operator value_type() { return *reinterpret_cast<value_type *>(this); } // never called
|
||||
operator T &() const { return *reinterpret_cast<T *>(const_cast<rvalue_probe *>(this)); } // never called
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
rvalue_probe<T> const make_probe(T const &t);
|
||||
rvalue_probe<T> const make_probe(T const &)
|
||||
{
|
||||
return rvalue_probe<T>();
|
||||
}
|
||||
|
||||
# define BOOST_FOREACH_IS_RVALUE(COL) \
|
||||
boost::foreach_detail_::and_( \
|
||||
boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \
|
||||
, BOOST_FOREACH_PROTECT(boost::foreach_detail_::is_rvalue_( \
|
||||
, (true ? 0 : boost::foreach_detail_::is_rvalue_( \
|
||||
(true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0)))
|
||||
|
||||
#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
|
||||
@@ -717,9 +749,124 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
return *auto_any_cast<iter_t, boost::mpl::false_>(cur);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// rbegin
|
||||
//
|
||||
template<typename T, typename C>
|
||||
inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>
|
||||
rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
|
||||
{
|
||||
return boost::rbegin(auto_any_cast<T, C>(col));
|
||||
}
|
||||
|
||||
template<typename T, typename C>
|
||||
inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>
|
||||
rbegin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
|
||||
typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator;
|
||||
return iterator(boost::rbegin(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
|
||||
}
|
||||
|
||||
#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
|
||||
template<typename T>
|
||||
auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>
|
||||
rbegin(auto_any_t col, type2type<T, const_> *, bool *)
|
||||
{
|
||||
return boost::rbegin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
template<typename T, typename C>
|
||||
inline auto_any<reverse_iterator<T *> >
|
||||
rbegin(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings
|
||||
{
|
||||
T *p = auto_any_cast<T *, boost::mpl::false_>(col);
|
||||
while(0 != *p)
|
||||
++p;
|
||||
return reverse_iterator<T *>(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// rend
|
||||
//
|
||||
template<typename T, typename C>
|
||||
inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>
|
||||
rend(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
|
||||
{
|
||||
return boost::rend(auto_any_cast<T, C>(col));
|
||||
}
|
||||
|
||||
template<typename T, typename C>
|
||||
inline auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type>
|
||||
rend(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
|
||||
typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iterator;
|
||||
return iterator(boost::rend(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
|
||||
}
|
||||
|
||||
#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
|
||||
template<typename T>
|
||||
auto_any<BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, const_>::type>
|
||||
rend(auto_any_t col, type2type<T, const_> *, bool *)
|
||||
{
|
||||
return boost::rend(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
|
||||
template<typename T, typename C>
|
||||
inline auto_any<reverse_iterator<T *> >
|
||||
rend(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings
|
||||
{
|
||||
return reverse_iterator<T *>(auto_any_cast<T *, boost::mpl::false_>(col));
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// rdone
|
||||
//
|
||||
template<typename T, typename C>
|
||||
inline bool rdone(auto_any_t cur, auto_any_t end, type2type<T, C> *)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t;
|
||||
return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// rnext
|
||||
//
|
||||
template<typename T, typename C>
|
||||
inline void rnext(auto_any_t cur, type2type<T, C> *)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t;
|
||||
++auto_any_cast<iter_t, boost::mpl::false_>(cur);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// rderef
|
||||
//
|
||||
template<typename T, typename C>
|
||||
inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type
|
||||
rderef(auto_any_t cur, type2type<T, C> *)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator<T, C>::type iter_t;
|
||||
return *auto_any_cast<iter_t, boost::mpl::false_>(cur);
|
||||
}
|
||||
|
||||
} // namespace foreach_detail_
|
||||
} // namespace boost
|
||||
|
||||
// Suppress a bogus code analysis warning on vc8+
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
# define BOOST_FOREACH_SUPPRESS_WARNINGS() __pragma(warning(suppress:6001))
|
||||
#else
|
||||
# define BOOST_FOREACH_SUPPRESS_WARNINGS()
|
||||
#endif
|
||||
|
||||
// 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, boost::foreach_detail_::is_const_(COL)))
|
||||
@@ -745,7 +892,7 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
|
||||
// No variable is needed to track the rvalue-ness of the collection expression
|
||||
# define BOOST_FOREACH_PREAMBLE() \
|
||||
/**/
|
||||
BOOST_FOREACH_SUPPRESS_WARNINGS()
|
||||
|
||||
// Evaluate the collection expression
|
||||
# define BOOST_FOREACH_EVALUATE(COL) \
|
||||
@@ -763,6 +910,7 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
|
||||
// Declare a variable to track the rvalue-ness of the collection expression
|
||||
# define BOOST_FOREACH_PREAMBLE() \
|
||||
BOOST_FOREACH_SUPPRESS_WARNINGS() \
|
||||
if (bool _foreach_is_rvalue = false) {} else
|
||||
|
||||
// Evaluate the collection expression, and detect if it is an lvalue or and rvalue
|
||||
@@ -788,7 +936,7 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
|
||||
// No variable is needed to track the rvalue-ness of the collection expression
|
||||
# define BOOST_FOREACH_PREAMBLE() \
|
||||
/**/
|
||||
BOOST_FOREACH_SUPPRESS_WARNINGS()
|
||||
|
||||
// Evaluate the collection expression
|
||||
# define BOOST_FOREACH_EVALUATE(COL) \
|
||||
@@ -808,7 +956,7 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
|
||||
// No variable is needed to track the rvalue-ness of the collection expression
|
||||
# define BOOST_FOREACH_PREAMBLE() \
|
||||
/**/
|
||||
BOOST_FOREACH_SUPPRESS_WARNINGS()
|
||||
|
||||
// Evaluate the collection expression
|
||||
# define BOOST_FOREACH_EVALUATE(COL) \
|
||||
@@ -853,6 +1001,34 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
_foreach_cur \
|
||||
, BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
#define BOOST_FOREACH_RBEGIN(COL) \
|
||||
boost::foreach_detail_::rbegin( \
|
||||
_foreach_col \
|
||||
, BOOST_FOREACH_TYPEOF(COL) \
|
||||
, BOOST_FOREACH_SHOULD_COPY(COL))
|
||||
|
||||
#define BOOST_FOREACH_REND(COL) \
|
||||
boost::foreach_detail_::rend( \
|
||||
_foreach_col \
|
||||
, BOOST_FOREACH_TYPEOF(COL) \
|
||||
, BOOST_FOREACH_SHOULD_COPY(COL))
|
||||
|
||||
#define BOOST_FOREACH_RDONE(COL) \
|
||||
boost::foreach_detail_::rdone( \
|
||||
_foreach_cur \
|
||||
, _foreach_end \
|
||||
, BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
#define BOOST_FOREACH_RNEXT(COL) \
|
||||
boost::foreach_detail_::rnext( \
|
||||
_foreach_cur \
|
||||
, BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
#define BOOST_FOREACH_RDEREF(COL) \
|
||||
boost::foreach_detail_::rderef( \
|
||||
_foreach_cur \
|
||||
, BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BOOST_FOREACH
|
||||
//
|
||||
@@ -890,4 +1066,22 @@ deref(auto_any_t cur, type2type<T, C> *)
|
||||
if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \
|
||||
for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BOOST_REVERSE_FOREACH
|
||||
//
|
||||
// For iterating over collections in reverse order. In
|
||||
// all other respects, BOOST_REVERSE_FOREACH is like
|
||||
// BOOST_FOREACH.
|
||||
//
|
||||
#define BOOST_REVERSE_FOREACH(VAR, COL) \
|
||||
BOOST_FOREACH_PREAMBLE() \
|
||||
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_RBEGIN(COL)) {} else \
|
||||
if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_REND(COL)) {} else \
|
||||
for (bool _foreach_continue = true; \
|
||||
_foreach_continue && !BOOST_FOREACH_RDONE(COL); \
|
||||
_foreach_continue ? BOOST_FOREACH_RNEXT(COL) : (void)0) \
|
||||
if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \
|
||||
for (VAR = BOOST_FOREACH_RDEREF(COL); !_foreach_continue; _foreach_continue = true)
|
||||
|
||||
#endif
|
||||
|
||||
11
test/Jamfile.v2
Executable file → Normal file
11
test/Jamfile.v2
Executable file → Normal file
@@ -8,16 +8,27 @@ import testing ;
|
||||
test-suite "foreach"
|
||||
: [ run stl_byval.cpp ]
|
||||
[ run stl_byref.cpp ]
|
||||
[ run stl_byval_r.cpp ]
|
||||
[ run stl_byref_r.cpp ]
|
||||
[ run array_byval.cpp ]
|
||||
[ run array_byref.cpp ]
|
||||
[ run array_byval_r.cpp ]
|
||||
[ run array_byref_r.cpp ]
|
||||
[ run cstr_byval.cpp ]
|
||||
[ run cstr_byref.cpp ]
|
||||
[ run cstr_byval_r.cpp ]
|
||||
[ run cstr_byref_r.cpp ]
|
||||
[ run pair_byval.cpp ]
|
||||
[ run pair_byref.cpp ]
|
||||
[ run pair_byval_r.cpp ]
|
||||
[ run pair_byref_r.cpp ]
|
||||
[ run user_defined.cpp ]
|
||||
[ run call_once.cpp ]
|
||||
[ run rvalue_const.cpp ]
|
||||
[ run rvalue_nonconst.cpp ]
|
||||
[ run rvalue_const_r.cpp ]
|
||||
[ run rvalue_nonconst_r.cpp ]
|
||||
[ run dependent_type.cpp ]
|
||||
[ run misc.cpp ]
|
||||
[ compile noncopyable.cpp ]
|
||||
;
|
||||
|
||||
48
test/array_byref_r.cpp
Normal file
48
test/array_byref_r.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef int foreach_container_type[5];
|
||||
typedef int const foreach_const_container_type[5];
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
int my_array[5] = { 1,2,3,4,5 };
|
||||
int const (&my_const_array)[5] = my_array;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
// non-const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_array, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_c_r(my_const_array, "\5\4\3\2\1"));
|
||||
|
||||
// mutate the mutable collections
|
||||
mutate_foreach_byref_r(my_array);
|
||||
|
||||
// compare the mutated collections to the actual results
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_array, "\6\5\4\3\2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
test/array_byval_r.cpp
Normal file
44
test/array_byval_r.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef int foreach_container_type[5];
|
||||
typedef int const foreach_const_container_type[5];
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
int my_array[5] = { 1,2,3,4,5 };
|
||||
int const (&my_const_array)[5] = my_array;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_array);
|
||||
|
||||
// non-const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_n_r(my_array, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_c_r(my_const_array, "\5\4\3\2\1"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
49
test/cstr_byref_r.cpp
Normal file
49
test/cstr_byref_r.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef char *foreach_container_type;
|
||||
typedef char const *foreach_const_container_type;
|
||||
typedef char foreach_value_type;
|
||||
typedef char &foreach_reference_type;
|
||||
typedef char const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
char my_ntcs_buffer[] = "\1\2\3\4\5";
|
||||
char *my_ntcs = my_ntcs_buffer;
|
||||
char const *my_const_ntcs = my_ntcs;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
// non-const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_ntcs, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_c_r(my_const_ntcs, "\5\4\3\2\1"));
|
||||
|
||||
// mutate the mutable collections
|
||||
mutate_foreach_byref_r(my_ntcs);
|
||||
|
||||
// compare the mutated collections to the actual results
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_ntcs, "\6\5\4\3\2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
45
test/cstr_byval_r.cpp
Normal file
45
test/cstr_byval_r.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef char *foreach_container_type;
|
||||
typedef char const *foreach_const_container_type;
|
||||
typedef char foreach_value_type;
|
||||
typedef char &foreach_reference_type;
|
||||
typedef char const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
char my_ntcs_buffer[] = "\1\2\3\4\5";
|
||||
char *my_ntcs = my_ntcs_buffer;
|
||||
char const *my_const_ntcs = my_ntcs;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_ntcs);
|
||||
|
||||
// non-const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_n_r(my_ntcs, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_c_r(my_const_ntcs, "\5\4\3\2\1"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
test/misc.cpp
Normal file
47
test/misc.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// misc.cpp
|
||||
//
|
||||
// (C) Copyright Eric Niebler 2008.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
4 March 2008 : Initial version.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
struct xxx : std::vector<int>
|
||||
{
|
||||
virtual ~xxx() = 0;
|
||||
};
|
||||
|
||||
void test_abstract(xxx& rng)
|
||||
{
|
||||
BOOST_FOREACH (int x, rng)
|
||||
{
|
||||
(void)x;
|
||||
}
|
||||
}
|
||||
|
||||
struct yyy : std::vector<int>
|
||||
{
|
||||
void test()
|
||||
{
|
||||
BOOST_FOREACH(int x, *this)
|
||||
{
|
||||
(void)x;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
50
test/pair_byref_r.cpp
Normal file
50
test/pair_byref_r.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
13 December 2004 : Initial version.
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef std::pair<int*,int*> foreach_container_type;
|
||||
typedef std::pair<int const*,int const*> const foreach_const_container_type;
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
int my_array[] = { 1,2,3,4,5 };
|
||||
std::pair<int*,int*> my_pair(my_array,my_array+5);
|
||||
std::pair<int const*,int const*> const my_const_pair(my_array,my_array+5);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
// non-const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_pair, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_c_r(my_const_pair, "\5\4\3\2\1"));
|
||||
|
||||
// mutate the mutable collections
|
||||
mutate_foreach_byref_r(my_pair);
|
||||
|
||||
// compare the mutated collections to the actual results
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_pair, "\6\5\4\3\2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
45
test/pair_byval_r.cpp
Normal file
45
test/pair_byval_r.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef std::pair<int*,int*> foreach_container_type;
|
||||
typedef std::pair<int const*,int const*> const foreach_const_container_type;
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
int my_array[] = { 1,2,3,4,5 };
|
||||
std::pair<int*,int*> my_pair(my_array,my_array+5);
|
||||
std::pair<int const*,int const*> const my_const_pair(my_array,my_array+5);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
boost::mpl::true_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_pair);
|
||||
|
||||
// non-const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_n_r(my_pair, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_c_r(my_const_pair, "\5\4\3\2\1"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
test/rvalue_const.cpp
Executable file → Normal file
3
test/rvalue_const.cpp
Executable file → Normal file
@@ -13,7 +13,10 @@
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifdef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
|
||||
// ignore error during Microsoft Code Analysis
|
||||
#if !defined(_PREFAST_)
|
||||
# error Expected failure : const rvalues disallowed
|
||||
#endif
|
||||
#else
|
||||
|
||||
std::vector<int> const get_vector()
|
||||
|
||||
44
test/rvalue_const_r.cpp
Normal file
44
test/rvalue_const_r.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// (C) Copyright Eric Niebler 2005.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifdef BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
|
||||
// ignore error during Microsoft Code Analysis
|
||||
#if !defined(_PREFAST_)
|
||||
# error Expected failure : const rvalues disallowed
|
||||
#endif
|
||||
#else
|
||||
|
||||
std::vector<int> const get_vector()
|
||||
{
|
||||
return std::vector<int>(4, 4);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
BOOST_REVERSE_FOREACH(int i, get_vector())
|
||||
{
|
||||
counter += i;
|
||||
}
|
||||
|
||||
BOOST_CHECK(16 == counter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
41
test/rvalue_nonconst_r.cpp
Normal file
41
test/rvalue_nonconst_r.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// (C) Copyright Eric Niebler 2005.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifdef BOOST_FOREACH_NO_RVALUE_DETECTION
|
||||
# error Expected failure : rvalues disallowed
|
||||
#else
|
||||
|
||||
std::vector<int> get_vector()
|
||||
{
|
||||
return std::vector<int>(4, 4);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
BOOST_REVERSE_FOREACH(int i, get_vector())
|
||||
{
|
||||
counter += i;
|
||||
}
|
||||
|
||||
BOOST_CHECK(16 == counter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
62
test/stl_byref_r.cpp
Normal file
62
test/stl_byref_r.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005: Initial version.
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef std::list<int> foreach_container_type;
|
||||
typedef std::list<int> const foreach_const_container_type;
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// initialize a std::list<int>
|
||||
std::list<int> make_list()
|
||||
{
|
||||
std::list<int> l;
|
||||
l.push_back(1);
|
||||
l.push_back(2);
|
||||
l.push_back(3);
|
||||
l.push_back(4);
|
||||
l.push_back(5);
|
||||
return l;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
std::list<int> my_list = make_list();
|
||||
std::list<int> const &my_const_list = my_list;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
// non-const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_list, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by reference
|
||||
BOOST_CHECK(sequence_equal_byref_c_r(my_const_list, "\5\4\3\2\1"));
|
||||
|
||||
// mutate the mutable collections
|
||||
mutate_foreach_byref_r(my_list);
|
||||
|
||||
// compare the mutated collections to the actual results
|
||||
BOOST_CHECK(sequence_equal_byref_n_r(my_list, "\6\5\4\3\2"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
60
test/stl_byval_r.cpp
Normal file
60
test/stl_byval_r.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// stl_byval.cpp
|
||||
///
|
||||
// (C) Copyright Eric Niebler 2004.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
/*
|
||||
Revision history:
|
||||
25 August 2005 : Initial version.
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <boost/test/minimal.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define the container types, used by utility.hpp to generate the helper functions
|
||||
typedef std::list<int> foreach_container_type;
|
||||
typedef std::list<int> const foreach_const_container_type;
|
||||
typedef int foreach_value_type;
|
||||
typedef int &foreach_reference_type;
|
||||
typedef int const &foreach_const_reference_type;
|
||||
|
||||
#include "./utility.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// initialize a std::list<int>
|
||||
std::list<int> make_list()
|
||||
{
|
||||
std::list<int> l;
|
||||
l.push_back(1);
|
||||
l.push_back(2);
|
||||
l.push_back(3);
|
||||
l.push_back(4);
|
||||
l.push_back(5);
|
||||
return l;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// define some containers
|
||||
//
|
||||
std::list<int> my_list = make_list();
|
||||
std::list<int> const &my_const_list = my_list;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// test_main
|
||||
//
|
||||
int test_main( int, char*[] )
|
||||
{
|
||||
boost::mpl::false_ *p = BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(my_list);
|
||||
|
||||
// non-const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_n_r(my_list, "\5\4\3\2\1"));
|
||||
|
||||
// const containers by value
|
||||
BOOST_CHECK(sequence_equal_byval_c_r(my_const_list, "\5\4\3\2\1"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
64
test/utility.hpp
Executable file → Normal file
64
test/utility.hpp
Executable file → Normal file
@@ -76,4 +76,68 @@ inline void mutate_foreach_byref( foreach_container_type & rng )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sequence_equal_byval_n_r
|
||||
inline bool sequence_equal_byval_n_r( foreach_container_type & rng, char const * result )
|
||||
{
|
||||
BOOST_REVERSE_FOREACH( foreach_value_type i, rng )
|
||||
{
|
||||
if(0 == *result || i != *result)
|
||||
return false;
|
||||
++result;
|
||||
}
|
||||
return 0 == *result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sequence_equal_byval_c_r
|
||||
inline bool sequence_equal_byval_c_r( foreach_const_container_type & rng, char const * result )
|
||||
{
|
||||
BOOST_REVERSE_FOREACH( foreach_value_type i, rng )
|
||||
{
|
||||
if(0 == *result || i != *result)
|
||||
return false;
|
||||
++result;
|
||||
}
|
||||
return 0 == *result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sequence_equal_byref_n_r
|
||||
inline bool sequence_equal_byref_n_r( foreach_container_type & rng, char const * result )
|
||||
{
|
||||
BOOST_REVERSE_FOREACH( foreach_reference_type i, rng )
|
||||
{
|
||||
if(0 == *result || i != *result)
|
||||
return false;
|
||||
++result;
|
||||
}
|
||||
return 0 == *result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sequence_equal_byref_c_r
|
||||
inline bool sequence_equal_byref_c_r( foreach_const_container_type & rng, char const * result )
|
||||
{
|
||||
BOOST_REVERSE_FOREACH( foreach_const_reference_type i, rng )
|
||||
{
|
||||
if(0 == *result || i != *result)
|
||||
return false;
|
||||
++result;
|
||||
}
|
||||
return 0 == *result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// mutate_foreach_byref
|
||||
//
|
||||
inline void mutate_foreach_byref_r( foreach_container_type & rng )
|
||||
{
|
||||
BOOST_REVERSE_FOREACH( foreach_reference_type i, rng )
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user