开发者

Implementing for(auto item : container) in VC2010

开发者 https://www.devze.com 2023-01-15 19:10 出处:网络
I wanted to create a little macro to simulate for(auto item : container) in VC2010 which I can then replace with the real construct when it\'s release开发者_StackOverflow中文版d.

I wanted to create a little macro to simulate for(auto item : container) in VC2010 which I can then replace with the real construct when it's release开发者_StackOverflow中文版d.

There is BOOST_FOREACH, however I would like auto support.

I've tried creating a macro. However it fails when the dereferenced iterator is a constant type.

#define _LIB_FOREACH_LINENAME_CAT(name, line) name##line
#define _LIB_FOREACH_LINENAME(name, line) _LIB_FOREACH_LINENAME_CAT(name, line)

#define LIB_AUTO_FOREACH(item, expr) \
    decltype((expr))&& _LIB_FOREACH_LINENAME(con, __LINE__)((expr)); auto _LIB_FOREACH_LINENAME(it, __LINE__) = _LIB_FOREACH_LINENAME(con, __LINE__).begin(); for(auto (item) = *_LIB_FOREACH_LINENAME(con, __LINE__).begin(); _LIB_FOREACH_LINENAME(it, __LINE__) != _LIB_FOREACH_LINENAME(con, __LINE__).end(); ++_LIB_FOREACH_LINENAME(it, __LINE__), (item) = *_LIB_FOREACH_LINENAME(it, __LINE__))

Anyone up for the challenge to correct mine or find a working implementation?

EDIT:

Notice that (expr) should only be evaluated once.


There is BOOST_FOREACH, however I would like auto support.

BOOST_FOREACH appears to support the C++0x auto keyword alright.

As your macro is, boost's one is superior. It also works for arrays (and probably zero-terminated char arrays) and lets you use references for the loop variable, rather than making it appear from the thin air.


Instead of

decltype((expr))&&

you should probably just write

auto&&

A problem with your approach is that it doesn't work with ranges that don't provide begin/end member functions (such as arrays). The proposed C++0x for-range loop makes use of free begin/end functions and argument dependent lookup to solve this.

Perhaps it's a good idea to include the code block as macro parameter:

#include <cstddef>

namespace for_range_helpers {

template<class Container>
auto begin(Container& c) -> decltype(c.begin())
{ return c.begin(); }

template<class Container>
auto end(Container& c) -> decltype(c.end())
{ return c.end(); }

template<class T, std::size_t N>
T* begin(T (&array)[N])
{ return array+0; }

template<class T, std::size_t N>
T* end(T (&array)[N])
{ return array+N; }

} // namespace for_range_helpers

#define FOR_RANGE(init_,expression_,...) \
    do { \
        using ::for_range_helpers::begin; \
        using ::for_range_helpers::end; \
        auto&& range_ = expression_; \
        for (auto iter_ = begin(range_), end_ = end(range_); \
            iter_ != end_; ++iter_) \
        { \
            init_ = *iter_; \
            __VA_ARGS__ \
        } \
    } while (0)

#include <iostream>
#include <vector>

int main()
{
    int arr[] = {2,3,5,7,11};
    std::vector<int> vec;
    FOR_RANGE(auto i, arr,
        vec.push_back(i);
    );
    FOR_RANGE(auto i, vec,
        std::cout << ' ' << i;
    );
    std::cout << '\n';
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号