foreach для бедных
От: _nn_ www.nemerleweb.com
Дата: 08.04.08 10:05
Оценка:
Отличается от 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)))
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.