LINUX.ORG.RU

foreach в c++

 ,


1

4

Как я ждал этого!!!

Начал писать на php и использовать тамошний foreach. Удобная конструкция скажу я вам; заметил, что обычным for вообще почти перестал пользоваться. На C++ же делал по-старинке/по-привычке: for (int i=0;i<N;i++) . Это раз. Кроме того, в C++ очень напрягала работа с STL/итераторами: монструозные конструкции выходят.

Про развитие C++ читал, но никак не доходили руки. И вот решил попробовать:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
  vector<uint> v;

  v.push_back(3);
  v.push_back(5);
  v.push_back(6);

  // Вот здесь!!!
  for(auto i:v)
    cout << i << " ";

  cout << "\n";

  return 0;
}
$ g++ -std=c++11 delme3.cpp -o delme3 && ./delme3
3 5 6
Да здравствует более читабельный код!!!

Если кто еще не пробовал - рекомендую!

★★★★★

Последнее исправление: Kroz (всего исправлений: 1)
Ответ на: комментарий от quiet_readonly

Нормальный синтаксис для итерирования по hasttable-образным и в случае необходимости по паре индекс-элемент в стиле ML'ей.

aedeph_ ★★
()
Ответ на: комментарий от beastie

Наверно я просто не перевариваю плюсы

Избранные теги: ansi c

Ну, ты понял :)

anonymous
()

Надо так. for(auto &i:v) cout << i << " ";

иначе элементы копируются.

Это уж совсем по старинке

for (int i=0;i<N;i++)

for (int i=0;i<N;++i)

иначе так же лишнее создание копии объекта

SergikXP
()
Ответ на: комментарий от x0r

ну и да, копирование не нужно: for (auto& i: v)

Да, спасибо за совет.

к сожалению если в цикле нужно по итератору ухнуть элемент из коллекции, то это все превращается в обычный for()

В смысле когда нужно подправить индекс? Наверное.
Хотя, если можно сделать for (auto *i: v) , и i - итератор, то можно будет. Я очень неуверен в этом варианте, но дома поэксперементирую.

Kroz ★★★★★
() автор топика

в Qt это нужно осторожно использовать, если контейнер не константный, то вызовется неконстантный begin(), что приведет к глубокому копированию контейнера

dt1 ★★
()
Ответ на: комментарий от visual

В Qt лучше было сделано

Чем лучше-то? Особенно весело, если в контейнере хранится что-то типа пар, пишешь:

Q_FOREACH(QPair<QString, QString> value, container)
{...}
И обламываешься на запятой потому что это макросы.

Впрочем, авто и тут спасёт.

DarkEld3r ★★★★★
()
Ответ на: комментарий от grondek

Я бы за auto расстреливал.

Я тоже сторонник явно тип указывать во многих случаях. Не есть немало исключений. Например:

MyMegaSuperCoolLongClass *p = new MyMegaSuperCoolLongClass; // что тут даст явное указание типа?
auto *p = new MyMegaSuperCoolLongClass; // так ведь удобнее

// Аналогично:
MyMegaSuperCoolLongClass *p = static_cast<MyMegaSuperCoolLongClass *>(somePointer);
auto *p = static_cast<MyMegaSuperCoolLongClass *>(somePointer);
Нет лишнего доблирования, проще читать код, меньше шансов ошибиться.

DarkEld3r ★★★★★
()
Ответ на: комментарий от andreyu

Пример?

Когда тебе этот тип/итератор нужен только один раз. Не имеет смысл городить

typedef vector<uint>::iterator TVectorI;
TVectorI v_i;
когда можно просто
vector<uint>::iterator v_i;

Не нахожу, поскольку информацию о типе нужно держать в голове

В данном случае тебе тип вообще не важен, тебе просто нужно чтобы i давало значение. И вообще, в нормальных программах i заменяют на что-то более осмыленное, что бы было понятно назначение переменной.

Kroz ★★★★★
() автор топика
Последнее исправление: Kroz (всего исправлений: 1)
Ответ на: комментарий от dt1

в Qt это нужно осторожно использовать, если контейнер не константный, то вызовется неконстантный begin(), что приведет к глубокому копированию контейнера

Не понял. Что значит не константный контейнер?
Контейнеры по определению по назначению предназначены для динамического наполнения. В смысле как правило.

Kroz ★★★★★
() автор топика
Ответ на: комментарий от andreyu

Не нахожу, поскольку информацию о типе нужно держать в голове. Никакой инфомации auto не дает.

Так можно дойти и до того, что венгерская нотация - это хорошо потому что больше информации даёт. Даже объявления переменной искать не надо - всё в имени содержится (опустим проблему синхронизации).

Хотя мне тоже не всегда нравится последняя «мода» везде где можно использовать вывод типов.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Kroz

Не понял. Что значит не константный контейнер?
Контейнеры по определению по назначению предназначены для динамического наполнения. В смысле как правило.

В Qt много где используется разделение данных. То есть если ты копируешь контейнер/строку, то передаётся просто указатель. Но если одну из копий надо модифицировать, то чтобы это не отразилось на всеx остальных уже приходится копировать.

И если ты просто хотел пробежаться по содержимому не модифицируя, то можешь быть удивлён затратами на копирование. Хотя в данном случае, как уже сказали, это легко обойти.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Kroz

Когда тебе этот тип/итератор нужен только один раз. Не имеет смысл городить

Не соглашусь. Тем более, что для вектора не обязательно использовать итератор.

В данном случае тебе тип вообще не важен, тебе просто нужно чтобы i давало значение.

Какое значение дает i? Как мне это узнать, не глядя на тип?

И вообще, в нормальных программах i заменяют на что-то более осмыленное, что бы было понятно назначение переменной.

Ага, nIndex - офигенно умное решение.

andreyu ★★★★★
()
Ответ на: комментарий от DarkEld3r

Так можно дойти и до того, что венгерская нотация - это хорошо потому что больше информации даёт. Даже объявления переменной искать не надо - всё в имени содержится (опустим проблему синхронизации).

О какой венгерской нотации вы говорите? Их существует две - ситемная венгерская и венгерская для приложений. Одна говно (системная), другая действительно удобная.

andreyu ★★★★★
()
Ответ на: комментарий от Kroz

Что значит не константный контейнер?

константность от контекста зависит, например, контейнер может быть передан по константной ссылке или использоваться в константном методе класса
в таких случаях range-based for можно использовать

dt1 ★★
()
Ответ на: комментарий от Kroz

например так:

std::multiset<int> mySet;
for (auto i = mySet.begin(); i != mySet.end();) {
    if (i->toDelete()) {
        mySet.erase(i++);
    } else {
        doSmth(*i);
        ++i;
    }
}

в голову не приходит как сюда бахнуть foreach

x0r ★★★★★
()
Последнее исправление: x0r (всего исправлений: 3)
Ответ на: комментарий от beastie

А теперь представь то же самое с for (int i=0;i<N;i++).

f1xmAn ★★★★★
()
Ответ на: комментарий от beastie

ты просто не писал на джаббе. С++11 вообще превратили в джаббу, разве что без jre.

x0r ★★★★★
()
Ответ на: комментарий от DeVliegendeHollander

Оно назад не ходит, иногда это нужно. Иногда нужно ходить не по каждому элементу, а выборочно. Но т.к. для подавляющего большинства задач нужно пройтись по всем элементам, то это очень нужная фича. :-)

f1xmAn ★★★★★
()
Ответ на: комментарий от Kroz

На том месте, где ты вместо обычных массивов будешь использовать контейнеры STL. Например vector.

Как говорится, не дай Б-г так оголодать.

А вы, кстати, часто полностью обходите контейнеры итераторами? Ну, сколько приблизительно раз на 1000 SLOC?

Я без подколки спрашиваю, действительно интересно. Лично мне кажется что это довольно редкая операция, и никаких чувств по поводу того что это можно записать компактнее не испытываю.

Но у меня, возможно, деформация восприятия, и с этим нужно что-то делать

anonymous
()
Ответ на: комментарий от anonymous

А вы, кстати, часто полностью обходите контейнеры итераторами?

Благодаря алгоритмам stl (find, count, copy, replace, transform, bounds, их вариантам, etc, etc, ) «for» действительно используется редко. У меня в проектах - в основном всякие отладочные выводы, временные подпорки, невычищенные закомментированные куски и т.п.

Но в с++11 много других плюшек которые используются часто (по предыдущему абзацу легко понять какие); просто у ТС протекла криокамера и он радуется простенькому сахарку.

anonymous
()
Ответ на: комментарий от BlackHawk

Я знаю, у меня есть знакомый работающий плюсист, примерно такое же нагородил и сказал, что это, дескать, точно так же. Хотя, наверное, те, кому это нужно, давно имеют свои наработки и просто подключают хедеры в нужный момент:)

cdshines ★★★★★
()
Ответ на: комментарий от Kroz

Не знаю, кому что нужно, тот по тому и пробегается:)

cdshines ★★★★★
()
Ответ на: комментарий от yoghurt

Не спорю, да) Это из смоллтока в руби появились эти рантаймовые send, class_eval и т.д? Бесполезно в большинстве случаев, но красиво же!

cdshines ★★★★★
()
Ответ на: комментарий от anonymous

Пиши на асме, не выделывайся.

Анон, ну ты че?

Смотри, у тебя есть два высказывания: «ты НЕ пишешь на асме» И (коньюнкция) «ты выделываешься». Делаешь инверсию (ну, чтобы потребовать не делать так), применяешь к получившемуся правило де Моргана и получается «пиши на асме ИЛИ не выделывайся». Эх

anonymous
()
Ответ на: комментарий от beastie

Да хотя бы тот же Go или Perl.

Perl — образец читабельности?! Лолчто.

Дожили, скоро лисперов начнут в модераторы /development/ брать.

anonymous
()

В 11ых плюсах есть еще много интересного. for - это мелочь, удобный синтаксический сахарок.

forCe
()

Хоть я и обещал, но тред выпилили и я просто оставлю это сдесь.

#include <stdio.h>
#include <stdint.h>

#define foreach(a, b)\
for(typeof(*(b)) * (a) = (b); (a) != ((b) + (sizeof((b))/sizeof(typeof(*(b))))); ++(a))
int main() {
  uint32_t vec[] = {123, 124, 125};
  foreach(it, vec)
    fprintf(stdout, "%u\n", *it);
  return 0;
}

procoder99
()
Ответ на: комментарий от anonymous

Не не называй этот щит неосиляторов указателей и синтаксиса сишкой.

Я вижу, и у меня появилась слеза, слеза из-за детей ущербных недоконпиляторов, которые отаслись в далёких 80-х.

procoder99
()

Да здравствует более читабельный код!!!
for(auto i:v)
cout << i << " ";

С точки зрения читабельности полный for читабельнее и понятнее.
Плюс, for без {} вообще нечитабельный
Но авт. итераторы удобная фича, да

comp00 ★★★★
()
Ответ на: комментарий от tailgunner

Пиши скобку как человек.

В плюсах ты для такого случая не получишь фореч тоже - юзай структуру, аля вектор, либо передавай длинну.

procoder99
()
Ответ на: комментарий от comp00

Для неосиляторов синтаксиса да, для людей понятно всё, и чем компактней это написанно - тем лучше.

Фор со скобками не читабельный. фор вообще не нужен, ибо есть дувайл/вайл.

Если в твоей голове не может отложится то, что фор без скобки - тело в одно строку(до ;), а так же ты не видишь форматирование - мне тебя жаль.

Не выставляй свои неосиляторский блажи как что-то важное.

procoder99
()
Ответ на: комментарий от procoder99

В плюсах ты для такого случая не получишь фореч тоже

Ты хоть понимаешь, что реализация foreach, которую ты «просто оставил», убога по сравнению с foreach плюсов? Хотя... если бы понимал, не запостил бы.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Нет, моя реализация идеальна и работает в 99% случаев.

Если бы ты осилил плюсы и понимал как работает форич, который просто берёт 2 поля по имени(begin, end).

Ещё раз - это банальный макрос, первый аргумент которого - это итератор, который итерируется инкрементом, а второй аргумент - из него берутся 2 иторатора begin и end. Если ты поменяешь их имена - твой форич тоже отвалится.

Поэтому банальное непонимании сишки, как и плюсов в частности.

procoder99
()
Ответ на: комментарий от tailgunner

И да, твоего случая в сишке по определению не может быть, только для строк( либо твои кастыли с флагом конца).

Поэтому ты можешь передавать структурку с бегином и ендом, как в плюсах, а этот юзать для случаев как у ТС"а.

procoder99
()
Ответ на: комментарий от procoder99

структурку с бегином и ендом, как в плюсах,

уточняющий вопрос - по-твоему два указателя хватит, чтоб реализовать range for как в С++?

wota ★★
()
Ответ на: комментарий от procoder99

Хватит и одного, но это слишком пофекальному для плюсовиков, а так да - 2-х хватит.

окай, давай вариант, который сможет пройтись по:

а) массиву
б) связному списку
в) бинарному дереву
г) файлу
д) генератору простых числ
е) хэш-мапе

и ес-но это должен быть один и тот же «foreach», а не десятки костылей

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
Ответ на: комментарий от wota

Как и любой плюсовик ты мыслишь узко. Ты проходишь не а-е, а по одному интерфейсу.

А вот этот интерфейс в твоих плюсах у тебя засчёт твоих нелюбимых десятков кастылей в кишках стл.

Что такое гинератор простых чилес - поясни, массив и файл есть одна и такж е сущность.

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

Зачем перебирать дерево и хешмап? Как я уже говорил - ты можешь впихнуть туда гетнекст, либо что-то типа этого. Ладно дерево, но перебирать хешмап извращение, а как ты собрался перебирать дерево я вообще не представлю.

Это очердная блаж плюсовиков, ты не видишь кастыля в фориче, но не понимаешь, что твои нелюбимые кастыли перекачевали в сами твои «контейнеры».

procoder99
()
Ответ на: комментарий от wota

Что ты не имеешь? Очередной гордый перебиратель хешмапов?

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

Такие кастыли я могу написать и на сишке - мне нетрудно, но мне они не нужны, как и не нужны никому, а то, что они у тебя есть - это лишь твоё неумение пилить вменяемо, когда тебе убогое стл позволяет делать ненужные вещи.

Поэтому банальная вера в плюсы и попытка доказать нужность любимой веры.

procoder99
()
Ответ на: комментарий от procoder99

Такие кастыли я могу написать и на сишке - мне нетрудно, но мне они не нужны, как и не нужны никому, а то, что они ТЕБЕ НУЖНЫ - это лишь твоё неумение пилить вменяемо по причине того, что убогое стл позволяет тебе делать убогие вещи.

Ошибка, хотя тебе они и не нужны, а это лишь жалкая попытка оправдаться.

procoder99
()
Ответ на: комментарий от comp00

И очередной сливер вылетел в трубу. Давай, скажи мне какой ты серьёзный интерпрайзер и как ты знаешь лучше меня.

А так да, теперь у тебя будет причина боятся писать ересь в тредах, а то вас никто не карает, а вы всё наглеете и наглеете.

procoder99
()
Ответ на: комментарий от procoder99

я могу написать

Ты можешь написать банальщину на уровне первокурсника и балаболить о том, сколь она совершенна, не более.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

На самом деле для меня с абстракцией. Не хотеть знать, что там внутри.
Зачем мне индексы, sizeof'ы, etc? Если я просто хочу применить вот эту функцию к каждому элементу. Не всем нравится эта идея, но мне кажется, что чем меньше лишнего кода (точнее сущностей), тем лучше.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.