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)

Начал писать на php и использовать тамошний foreach.

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

PHP

# Вот здесь!!!

Вы это, не увлекайтесь так :)

KennyMinigun ★★★★★
()

Ждем прокодера100500/суперхаккиллера100500, который на «сишке» будет все это генерить в компайлтайме, чтоб не загружать эту идиотскую недоделанную х86 с ее придурочным неполноценным кэшем и языками для неосиляторов лишними вычислениями. по-царски.

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

Ждем прокодера100500/суперхаккиллера100500

Давно я не заходил, это какой-то новый пациент, или просто кто-то напялил маскарадный костюм?

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

Наверно я просто не перевариваю плюсы. По крайней мере для меня абсолютно не очевидно, что творится в for. И у меня есть чуть-чуть с чем сравнить.

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

По крайней мере для меня абсолютно не очевидно, что творится в for.

Ну, это не должно быть проблемой - в спеках, как правило, всё чётко написано. Другое дело их раскуривать, это дааа :)

И у меня есть чуть-чуть с чем сравнить.

Ну? сказал «а», теперь говори «б» :)

Ignatik
()

Уже года два использую.. или три, не помню.

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

По крайней мере для меня абсолютно не очевидно, что творится в for.

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

Ты на них не пишешь → ты не вникаешь в инструмент, это нормально.

Оно раскрывается в обычную конструкцию с итератором и begin()/end().

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

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

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

Chaser_Andrey ★★★★★
()
Ответ на: комментарий от Chaser_Andrey
enumerable_instance.each {#...}
enumerable_instance.map {#...}
enumerable_instance.inject {#...}
enumerable_instance.select {#...}

Рубевое.

p.s. enumerable_instance - это инстанс любого класса с инжектированным модулем Enumerable и реализованным each, грубо говоря.

то есть можно не только по вектору/хэшу пробежаться, но и по чему захочешь.

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

foreach, оно, конешно, хорошо...но везде ли и всегда ли?

Это просто синтаксический сахар. Второй кусок делает ровно то же, что и первый, но не выглядит так ужасно.

for (std::vector<type_name>::[const_]iterator it = some_vector.begin(); it != some_vector.end(); ++it) 
{
   do_something(*it);
}

for (auto[ const]& i : some_vector)
{
   do_something(i);
}
BlackHawk
()
Ответ на: комментарий от visual

Эмм.. а чем таки лучше? Разделением аргументов запятой, а не двоеточием?

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

Вообще препроцессор проигнорирует такой комментарий, максимум warning выдаст.

CPP (который из GCC) уж точно ломается при виде такого: http://ideone.com/QjfkZt
Не знаю как там другие препроцессоры.

KennyMinigun ★★★★★
()

Так еще короче можно. Вместо push_back

    auto v = vector<int>{3, 5, 6};

    // или
    vector<int> v1 {3, 5, 6};

    // или вообще без вектора
    auto l = {3, 5, 6};
    for (auto el : l)
        cout << el << ' ';
alexeiz
()

Да здравствует более читабельный код!!!

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

Мда... Ну что тут сказать? Добро пожаловать в наше время! Где Вы только были до сих пор?

И да, Вы побольше описаний почитайте - удивитесь, сколько еще всего сладкого появилось. :)

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

Вы это, не увлекайтесь так :)

Всё, всё, исправил :)

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

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

Только там, как я понял a) нужно явно задавать тип переменной, что в случае контейнеров/итераторов не очень удобно и б) Цикл foreach - будьте аккуратны, Qt понимает только простые типы

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

то есть можно не только по вектору/хэшу пробежаться, но и по чему захочешь.

По любому контейнеру (который поддерживает итераторы). А по чему еще нужно?

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

Мда... Ну что тут сказать? Добро пожаловать в наше время! Где Вы только были до сих пор?

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

И да, Вы побольше описаний почитайте - удивитесь, сколько еще всего сладкого появилось. :)

А чем вы еще таким сладким пользуетесь? Интересует именно практика, а не демонстрация возможностей C++.

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

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

Ну, здесь auto в самый раз, не находите?
А так, я частично с вами согласен: нужно использовать аккуратно.

Да, кстати, вы обойму уже подготовили?
http://msdn.microsoft.com/en-us/library/vstudio/dd293667.aspx
We recommend that you use the auto keyword for most situations

Я рекомендую разрывные.

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

Ну, здесь auto в самый раз, не находите?

Тут нормально, примерчик маленький, и все равно, какого типа будут элемены массива: char, short int или long int.

Я рекомендую разрывные.

Полезно.

Хорошо, что я на текущей работе не пользуюсь msvs. Да и работаем мы с предыдущим стандартом C++.

grondek
()

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

Шёл 2013-й год...

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

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

#include <iostream>
#include <vector>
#include <string>

template<template <class, class...> class T, class P, class F, class ... Args>
auto map(T<P, Args...> const& container, F const& function) -> std::vector<decltype(function(std::declval<P>()))>
{
    std::vector<decltype(function(std::declval<P>()))> res;
    for (auto const& el : container)
    {
        res.push_back(function(el));
    }
    return res;
} 

int main()
{
    std::vector<std::string> v{"aaa", "bbbb", "cccccc"};
    auto l = map(v, [] (std::string const& x) { return x.length(); });
    for (auto i : l)
    {
        std::cout << i << std::endl;
    }
}

Можно сделать и так, чтобы возвращаемый тип контейнера совпадал с передаваемым, но мне лень.

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

Все он понимает. Неужели так сложно вынести объявление переменной текущего элемента списка за область цикла? Т.е. вместо:

QList< QMap<QString, QString> > branch;
...
// Пробегается QList
 foreach(QMap<QString, QString> current_branch, branch)
 {
  qDebug() << "Branch data:";
 
  // Пробегается QMap, для извлечения пар ключ-значение
  foreach(QString field_name, current_branch.keys())
   qDebug() << field_name << ":" << current_branch.value(field_name);
 }
писать
QList< QMap<QString, QString> > branch;
...
QMap<QString, QString> current_branch;
foreach(current_branch, branch)
 {
  qDebug() << "Branch data:";
 
  // Пробегается QMap, для извлечения пар ключ-значение
  foreach(QString field_name, current_branch.keys())
   qDebug() << field_name << ":" << current_branch.value(field_name);
 }

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

Если это читабельно — то я папа римский

Мысленно рукопожимаю.

Какой-то особой разницы между примером ТС и вот таким

#include <stdio.h>

int
main()
{
        unsigned int v[] = {3, 5, 6};
        size_t i;

        for (i=0; i< (sizeof(v) / sizeof (v[0])); i++) {
                printf("%u ", v[i]);
        }
        printf("\n");

        return 0;
}

не вижу.

В каком именно месте должна была появиться слеза радости?

И это не говоря уже о том что такое можно запустить хоть на микроконтроллере 10-летней давности, а что-то собранное с С++11 даже на какой-нибудь legacy Red Hat упаришься деплоить

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

Да хотя бы тот же Go

Надеюсь, ты шутишь.

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

В каком именно месте должна была появиться слеза радости?

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

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

Кроме того, в C++ очень напрягала работа с STL/итераторами: монструозные конструкции выходят.

typedef обошел вас стороной?

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

А чем вы еще таким сладким пользуетесь? Интересует именно практика, а не демонстрация возможностей C++.

Лямбды для асинхронных коллбэков (причём там есть подводные камни), спецификатор override, non-static member initializers, новая STL.

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

typedef обошел вас стороной?

Использовал. Кстати, не всегда уместно.

for(auto i:v) покрасивее будет, не находите?

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

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

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

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

к сожалению если в цикле нужно по итератору ухнуть элемент из коллекции

для этого есть std::remove_if, а в С++14 типы аргументов в лямбдах можно будет не указывать

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

Использовал. Кстати, не всегда уместно.

Пример?

for(auto i:v) покрасивее будет, не находите?

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

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

для этого есть std::remove_if, а в С++14 типы аргументов в лямбдах можно будет не указывать

for(auto)
   render(...);
for(auto)
   update(...);
remove_if(...);

Вместо одного цикла

for(iterator)
{
   render(...);
   update(...);
   if(exp) remove();
}

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

Все он понимает

Да ну? А если в контейнере не копируемые элементы? Или просто большие?

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