Реализация для (auto item: container) в VC2010 - PullRequest
2 голосов
/ 10 сентября 2010

Я хотел создать небольшой макрос для имитации (auto item: container) в VC2010, который я мог бы затем заменить на реальную конструкцию, когда она будет выпущена.

Существует BOOST_FOREACH, однако я хотел бы получить автоматическую поддержку.

Я пытался создать макрос.Однако он не работает, когда разыменованный итератор является константным типом.

#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__))

Кто-нибудь готов ответить на вызов, чтобы исправить мою или найти работающую реализацию?

РЕДАКТИРОВАТЬ:

Уведомлениеэто (expr) должно быть оценено только один раз.

Ответы [ 3 ]

3 голосов
/ 10 сентября 2010

Существует BOOST_FOREACH, однако я бы хотел автоматическую поддержку.

BOOST_FOREACH, кажется, хорошо поддерживает ключевое слово C ++ 0x auto.

Какваш макрос, буст один лучше.Он также работает с массивами (и, возможно, с нулевыми символами) и позволяет использовать ссылки для переменной цикла вместо того, чтобы показывать их из ничего.

2 голосов
/ 10 сентября 2010

Вместо

decltype((expr))&&

вам, вероятно, следует просто написать

auto&&

Проблема вашего подхода в том, что он не работает с диапазонами, которые не обеспечивают начало / конецфункции-члены (такие как массивы).Предлагаемый цикл C ++ 0x for-range использует свободные функции начала / конца и зависимый от аргумента поиск, чтобы решить эту проблему.

Возможно, будет хорошей идеей включить блок кода в качестве параметра макроса:

#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 голосов
/ 17 сентября 2010

В VS2010 вы также можете использовать Microsoft для каждого (auto i in v) расширения.Лично я предпочел бы кроссплатформенное решение Boosts.

См. Также здесь .

Возможно, можно написать макрос, который преобразует синтаксис C ++ 0x в синтаксис Microsoft.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...