Отличается от BOOST_FOREACH меньшей функциональностью: не проходят только тесты: noncopyable, rvalue_const, rvalue_nonconst.
Зато генерирует более оптимальный код.
Примечание: используется нативная поддержка for each в VC 8.0 и выше.
#include <vector>
#include <boost/array.hpp>
#include <iostream>
__declspec(noinline) void f()
{
// Regular array
int a[10] = {};
// Value
NN_FOREACH(int i, a)
std::cout << i;
// Reference to const
NN_FOREACH(int const& i, a)
std::cout << i;
// Reference to non Const
NN_FOREACH(int& i, a)
i = 1;
assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a));
}
__declspec(noinline) void g()
{
// Boost.Array
boost::array<int, 10> a = {};
// Value
NN_FOREACH(int i, a)
std::cout << i;
// Reference to const
NN_FOREACH(int const& i, a)
std::cout << i;
// Reference to non Const
NN_FOREACH(int& i, a)
i = 1;
assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a));
}
__declspec(noinline) void h()
{
// Std.Vector
std::vector<int> a(10);
// Value
NN_FOREACH(int i, a)
std::cout << i;
// Reference to const
NN_FOREACH(int const& i, a)
std::cout << i;
// Reference to non Const
NN_FOREACH(int& i, a)
i = 1;
assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a));
}
__declspec(noinline) void i()
{
// Std.Vector
std::vector<int> a(10);
// Value
for(std::vector<int>::const_iterator it = a.begin(), it_end = a.end();
it != it_end;
++it)
std::cout << *it;
// Reference to const
for(std::vector<int>::const_iterator it = a.begin(), it_end = a.end();
it != it_end;
++it)
std::cout << i;
// Reference to non Const
for(std::vector<int>::iterator it = a.begin(), it_end = a.end();
it != it_end;
++it)
*it = 1;
assert(std::find(boost::begin(a), boost::end(a), 0) == boost::end(a));
}
__declspec(noinline) void j()
{
// Char pointer
char a[] = "aaaaaaaaaa";
char* p = a;
// Value
NN_FOREACH(char i, p)
std::cout << i;
// Reference to const
NN_FOREACH(char const& i, p)
std::cout << i;
// Reference
NN_FOREACH(char& i, a)
i = 'a';
assert(std::find(boost::begin(a), boost::end(boost::as_literal(a)), 0) == boost::end(boost::as_literal(a)));
}
int main()
{
f();g();h();i();j();
}
Код:
#if !defined(_MSC_VER) || _MSC_VER < 1400 // VC 8.0-
#error Lightweight foreach works only with MS VC++ 8.0 and above
#endif
// Lightweight foreach
// Limitations:
// 1. Does not work with rvalues.
// If you define BOOST_FOREACH_LIGHT as BOOST_FOREACH_LIGHT, you must define also
// BOOST_FOREACH_NO_CONST_RVALUE_DETECTION and BOOST_FOREACH_NO_RVALUE_DETECTION
//
// 2. Currently does not work with noncopyable correctly
#include <boost/range/iterator_range.hpp>
#include <boost/range/as_literal.hpp>
namespace nn
{
namespace foreach
{
namespace detail
{
template< class T >
inline ::boost::iterator_range< BOOST_DEDUCED_TYPENAME ::boost::range_iterator<T*>::type >
make_iterator_range_ex_str(T* s)
{
return ::boost::make_iterator_range(::boost::begin( boost::as_literal(s))
, ::boost::end( boost::as_literal(s)));
}
} // namespace detail
template< class ForwardRange >
inline ::boost::iterator_range< BOOST_DEDUCED_TYPENAME ::boost::range_iterator<ForwardRange>::type >
make_iterator_range_ex( ForwardRange& r )
{
return ::boost::make_iterator_range(r);
}
inline ::boost::iterator_range< ::boost::range_iterator<char*>::type >
make_iterator_range_ex( char * r )
{
return detail::make_iterator_range_ex_str(r);
}
inline ::boost::iterator_range< ::boost::range_iterator<char const*>::type >
make_iterator_range_ex( char const* r )
{
return detail::make_iterator_range_ex_str(r);
}
inline ::boost::iterator_range< ::boost::range_iterator<wchar_t*>::type >
make_iterator_range_ex( wchar_t * r )
{
return detail::make_iterator_range_ex_str(r);
}
inline ::boost::iterator_range< ::boost::range_iterator<wchar_t const*>::type >
make_iterator_range_ex( wchar_t const* r )
{
return detail::make_iterator_range_ex_str(r);
}
} // namespace foreach
} // namespace nn
#define NN_FOREACH(var, col) \
for each(var in (::nn::foreach::make_iterator_range_ex(col)))