Как можно реализовать мой цикл for for ranged? - PullRequest
0 голосов
/ 29 декабря 2018

Мне действительно нравится Ranged-based-for-loop, который поддерживается C ++ 11 и выше.Я хотел бы по какой-то причине понять, чтобы смоделировать это.Вот пример:

// 1
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; X = *beg, ++beg)\

// 2
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; ++beg, X = *beg)\

// 3
#define ranged_for(X, T) \
    for (std::vector<int>::iterator beg{ T.begin() },\
        end{ T.end() }; beg != end; ++beg)\
            X = *beg, 



int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    auto i{ 0 };
    ranged_for(i, data)
        std::cout << i << std::endl;

    std::cout << std::endl;
    std::cin.get();
    return 0;
}

Как вы можете видеть выше, первый макрос не получает первый элемент 75, но вместо него значение 0 и последний отсутствует.Это потому, что я думаю, что в моем основном я печатаю x перед тем, как назначить его в части цикла после итерации.

  • Второй макрос приводит к сбою программы, потому что я думаю, что отмена ссылки на последний узел (сторожевой узел).

  • Третий работает нормальноно, как вы можете видеть после расширения макроса, я получу:

    i = *beg, std::cout << i << std::endl;
    

Это потому, что строка выше обрабатывается как один оператор.Есть ли лучший способ и объяснение.Спасибо всем хорошие парни!

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Это должно работать как для однострочных, так и для многострочных областей:

#define ranged_for(X, T) \
    for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it)

Или должна быть версия, которая может использоваться для автоматического вывода типа X, но для этого требуется дополнительный макрос:

#define ranged_for(X, T) \
    {decltype(T)::value_type X; for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it) {

#define range_end }}

int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    ranged_for(i, data)
        std::cout << i << std::endl;
    range_end
}
0 голосов
/ 29 декабря 2018

Почему вы так сильно противитесь C ++ ранжированию, основанному на циклах?

int i;
ranged_for(i, data)
    // ...

против

for(int i : data)

Вы должны были до этого объявить i.Вы не можете использовать ссылки таким образом!Теперь давайте представим, что нам удалось сделать это умнее:

ranged_for(int& i, data)

против

for(int& i : data)

Что вы получили?Использование запятой вместо двоеточия ???Честно говоря, это не стоит усилий.Сценарий, более интересный для рассмотрения:

auto i = data.end();
for(auto j = data.begin(); j != data.end(); ++j)
{
    if(someCondition)
        i = j;
}
if(i != data.end())
{
    // ...
}

Хорошо, это уже довольно редко.Во многих, если не в большинстве случаев, вы можете переместить внешнее тело if во внутреннее, добавив в конце команду break.И в этих немногих случаях вы все еще не можете сделать это - ну, тогда Я бы жил с явным циклом итератора - это не , что тяжело писать ...

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