Re[10]: range based for - первый/последний?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.03.19 19:29
Оценка:
Здравствуйте, rg45, Вы писали:

M>>ЗЫ Кстати, а зачем буст?


R>Затем, что в той версии gcc, что в ideone, этих функций просто еще нету. Требование "чтоб без буста" ты ведь позже ввел.


Ну, вообще я интересовался языковыми средствами C++ из новых стандартов, и думал, что, возможно, предусмотрено какое-то языковое средство для определения крайних случаев.


M>>Чем плох такой вариант:


R>Да ни чем не хуже. Только зачем ты этот топик создавал, если вариант обычного for тебя тоже устраивает, оказывается


Да если столько писанины в итоге, то уже как-то и не важно, в каком виде этот несчастный for будет
Маньяк Робокряк колесит по городу
Re[11]: range based for - первый/последний?
От: rg45 СССР  
Дата: 13.03.19 19:39
Оценка: +1
Здравствуйте, Marty, Вы писали:


M>Да если столько писанины в итоге, то уже как-то и не важно, в каком виде этот несчастный for будет


Ну смотри, я тут походу пьессы уже предоставил два варианта — один максимально универсальный
Автор: rg45
Дата: 13.03.19
, и его сложность как раз и обусловлена утиверсальностью. Второй вариант
Автор: rg45
Дата: 13.03.19
заточен под конткретное место использования. И я бы не сказал, что выглядит он слишком уж сложно:

    std::cout << *std::begin(array);
        
    for (const auto& item : boost::make_iterator_range(array, 1, 0))
    {
        std::cout << ", " << item;
    }


Неужели это сложнее или читается хуже чем:

   for (auto& a : cont)
   {
      auto first = &a == &cont.front();
  
      if (!first)
      {
          std::cout << ", ";
      }

      std::cout << item;
   }


Ты не согласен?
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 13.03.2019 19:41 rg45 . Предыдущая версия . Еще …
Отредактировано 13.03.2019 19:40 rg45 . Предыдущая версия .
Re[12]: range based for - первый/последний?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.03.19 19:51
Оценка: +1
Здравствуйте, rg45, Вы писали:


M>>Да если столько писанины в итоге, то уже как-то и не важно, в каком виде этот несчастный for будет


R>Ну смотри, я тут походу пьессы уже предоставил два варианта — один максимально универсальный
Автор: rg45
Дата: 13.03.19
, и его сложность как раз и обусловлена утиверсальностью. Второй вариант
Автор: rg45
Дата: 13.03.19
заточен под конткретное место использования. И я бы не сказал, что выглядит он слишком уж сложно:


Но он тянет буст.


R>Неужели это сложнее или читается хуже чем:


Ну, после того как ты его максимально удлиннил, то конечно этот вариант стал похуже


R>Ты не согласен?


Забей
Маньяк Робокряк колесит по городу
Re[13]: range based for - первый/последний?
От: rg45 СССР  
Дата: 13.03.19 20:00
Оценка:
Здравствуйте, Marty, Вы писали:


R>>Неужели это сложнее или читается хуже чем:


M>Ну, после того как ты его максимально удлиннил, то конечно этот вариант стал похуже



Да не вопрос, давай упростим, но только оба варианта!

    std::cout << cont.front();

    for (auto& a : boost::make_iterator_range(cont, 1, 0))
        std::cout << ", " << a;


   for (auto& a : cont)
   {
      if (&a != &cont.front())
          std::cout << ", ";

      std::cout << item;
   }
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[14]: range based for - первый/последний?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.03.19 20:05
Оценка:
Здравствуйте, rg45, Вы писали:


M>>Ну, после того как ты его максимально удлиннил, то конечно этот вариант стал похуже


R>Да не вопрос, давай упростим, но только оба варианта!


Нормас!
Маньяк Робокряк колесит по городу
Re[15]: range based for - первый/последний?
От: rg45 СССР  
Дата: 13.03.19 20:08
Оценка: :)
Здравствуйте, Marty, Вы писали:


R>>Да не вопрос, давай упростим, но только оба варианта!


M>Нормас!


Не, ты скажи, что я тебя убедил
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[16]: range based for - первый/последний?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.03.19 20:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>Да не вопрос, давай упростим, но только оба варианта!


M>>Нормас!


R>Не, ты скажи, что я тебя убедил


Неа

1) Таки буст.
2) Таки то, что с пустым вектором не работает. Это таки критичнее, чем то, что мой вариант не работает с произвольным контейнеромадаптером
Маньяк Робокряк колесит по городу
Re[17]: range based for - первый/последний?
От: rg45 СССР  
Дата: 13.03.19 20:29
Оценка:
Здравствуйте, Marty, Вы писали:

M>2) Таки то, что с пустым вектором не работает. Это таки критичнее, чем то, что мой вариант не работает с произвольным контейнеромадаптером


Ай, блин, я ждал, что ты это скажешь!

Лады, замечание справедливое, подчиняюсь.

    if (!cont.empty())
    {
        std::cout << cont.front();

        for (auto& a : boost::make_iterator_range(cont, 1, 0))
            std::cout << ", " << a;
    }


   for (auto& a : cont)
   {
      if (&a != &cont.front())
          std::cout << ", ";

      std::cout << item;
   }


По компактности соизмеримо. По надежности, и универсальности мой вариант лучше, ты вроде бы признаешь это. Но вот по читабельности мне мой вариант нравится больше: сразу видно, что первый элемент обрабатывается иначе, чем хвост — логика программы легче отслеживается.

Ну вот только буст остается. Но я лично против буста ничего не имею.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 13.03.2019 20:36 rg45 . Предыдущая версия . Еще …
Отредактировано 13.03.2019 20:33 rg45 . Предыдущая версия .
Re[18]: range based for - первый/последний?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 13.03.19 21:03
Оценка:
Здравствуйте, rg45, Вы писали:

M>>2) Таки то, что с пустым вектором не работает. Это таки критичнее, чем то, что мой вариант не работает с произвольным контейнеромадаптером


R>Ай, блин, я ждал, что ты это скажешь!


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


R>По компактности соизмеримо. По надежности, и универсальности мой вариант лучше, ты вроде бы признаешь это.


Согласен.


R>Но вот по читабельности мне мой вариант нравится больше: сразу видно, что первый элемент обрабатывается иначе, чем хвост — логика программы легче отслеживается.


Имхо — вкусовщина и дело привычки


R>Ну вот только буст остается. Но я лично против буста ничего не имею.


По возможности избегаю. Сейчас вообще продакшн код пишу для STMки, а там у кейла такая ситуёвина, что компилятор вроде допилили до 11го стандарта, а библиотеки — забыли, поленились, или бабла на это зажали. Это вроде даже не кейловская проблема, а армовская. Буст втуда вкорячивать не вижу особого смысла

С другой стороны, иногда пишу всякие утилитки для локального вспоможения на MSVC, C++17, а код, по возможности, для одних и тех же случаев стараюсь переиспользовать и там и там. Более новые стандарты пробую использовать только там, что в STMку точно не пролезет. А с нынешним достаточно резвым темпом принятия фич в стандарт буст таскать ради пары мелочей смысла не вижу
Маньяк Робокряк колесит по городу
Re: range based for - первый/последний?
От: B0FEE664  
Дата: 13.03.19 22:54
Оценка:
Здравствуйте, Marty, Вы писали:

M>Для цикла типа:

M>
M>for( autp a : cont)
M>{
M>    doWith(a);
M>}
M>

M>можно определить первый/последний элемент?

Можно, но сложно. Есть три варианта:
1) написать прокси для cont;
2) написать прокси для a;
3) написать прокси для тела цикла.

На мой взгляд последний вариант самый перспективный, но он же и самый труднопонимаемый/читаемый:
  std::function<void(int)> f = [&] (int n) { 
                                             f = [](int n){ std::cout << ", " << n; };
                                             std::cout << n;
                                           };
  for(auto item : v)
    f(item);


M>Для нового range-for'а есть какой-нибудь вариант?

Есть вот такой модный вариант, но он не то, что вы просите:
  if ( auto it = std::begin(v), itEnd = std::end(v); itEnd != it )
  {
    std::cout << *it;
    for(++it; itEnd != it; ++it)
    {
      std::cout << ", " << *it;
    }
  }
И каждый день — без права на ошибку...
Re: range based for - первый/последний?
От: PM  
Дата: 14.03.19 06:52
Оценка: 9 (2)
Здравствуйте, Marty, Вы писали:


M>для вывода разных списков и тп.


M>Для нового range-for'а есть какой-нибудь вариант?


Если только для вывода, то есть https://en.cppreference.com/w/cpp/experimental/ostream_joiner

#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
 
int main()
{
    int i[] = {1, 2, 3, 4, 5};
    std::copy(std::begin(i),
              std::end(i),
              std::experimental::make_ostream_joiner(std::cout, ", "));
}


Output:

1, 2, 3, 4, 5

Re[2]: range based for - первый/последний?
От: rg45 СССР  
Дата: 14.03.19 07:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

M>>Для нового range-for'а есть какой-нибудь вариант?

BFE>Есть вот такой модный вариант, но он не то, что вы просите:
BFE>
BFE>  if ( auto it = std::begin(v), itEnd = std::end(v); itEnd != it )
BFE>  {
BFE>    std::cout << *it;
BFE>    for(++it; itEnd != it; ++it)
BFE>    {
BFE>      std::cout << ", " << *it;
BFE>    }
BFE>  }
BFE>


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

  if (!std::empty(v))
  {
    std::cout << std::front(v);
    for(auto it = std::begin(v) + 1; it != std::end(v); ++it)
    {
      std::cout << ", " << *it;
    }
  }


Ну правда std::empty и std::front появляются только в С++17. Но их отсутствие легко восполняется, могу показать, если нужно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 14.03.2019 9:13 rg45 . Предыдущая версия . Еще …
Отредактировано 14.03.2019 8:13 rg45 . Предыдущая версия .
Отредактировано 14.03.2019 8:09 rg45 . Предыдущая версия .
Отредактировано 14.03.2019 7:57 rg45 . Предыдущая версия .
Re[3]: range based for - первый/последний?
От: B0FEE664  
Дата: 14.03.19 13:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Вот эта многоэтажность в условии глаз не радует совершенно.

Я пробовал так:
if ( auto [it, itEnd] = {std::begin(v), std::end(v)}; itEnd != it )

но не собралось.

R>Зачем вообще здесь что-то выдумывать, когда все предельно просто:

Затем, чтобы избежать вызова std::end(v) на каждую проверку условия цикла.
И каждый день — без права на ошибку...
Re[4]: range based for - первый/последний?
От: _NN_ www.nemerleweb.com
Дата: 14.03.19 13:30
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Здравствуйте, rg45, Вы писали:


R>>Вот эта многоэтажность в условии глаз не радует совершенно.

BFE>Я пробовал так:
BFE>
BFE>if ( auto [it, itEnd] = {std::begin(v), std::end(v)}; itEnd != it )
BFE>

BFE>но не собралось.

Начиная с C++17 типы std::begin и std::end не обязаны совпадать.
Собственно for-range разворачивается в такой код.
https://en.cppreference.com/w/cpp/language/range-for

До C++17
{

    auto && __range = range_expression ;
    for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement

    }

}


C++17
{

    auto && __range = range_expression ;
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for ( ; __begin != __end; ++__begin) {

        range_declaration = *__begin;
        loop_statement

    }

}



R>>Зачем вообще здесь что-то выдумывать, когда все предельно просто:

BFE>Затем, чтобы избежать вызова std::end(v) на каждую проверку условия цикла.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: range based for - первый/последний?
От: flаt  
Дата: 14.03.19 13:33
Оценка:
Здравствуйте, Marty, Вы писали:

M>Спс. Но вариант с булевым флагом имхо лучше


Прост, лаконичен, изящен. И нет лишних проверок внутри цикла.
Re[5]: range based for - первый/последний?
От: B0FEE664  
Дата: 14.03.19 13:46
Оценка:
Здравствуйте, _NN_, Вы писали:

BFE>>Я пробовал так:

BFE>>
BFE>>if ( auto [it, itEnd] = {std::begin(v), std::end(v)}; itEnd != it )
BFE>>

BFE>>но не собралось.
_NN>Начиная с C++17 типы std::begin и std::end не обязаны совпадать.

Дело не в этом.
Вот такая конструкция не работает:
  int i1 = 1;
  int i2 = 2;
  auto [a, b] = {i1, i2};

А жаль.

проверял тут
И каждый день — без права на ошибку...
Re[4]: range based for - первый/последний?
От: rg45 СССР  
Дата: 14.03.19 13:58
Оценка:
Здравствуйте, B0FEE664, Вы писали:

R>>Зачем вообще здесь что-то выдумывать, когда все предельно просто:

BFE>Затем, чтобы избежать вызова std::end(v) на каждую проверку условия цикла.

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

Не будет там никакого ВЫЗОВА — в подавляющем-подавляющем большинстве случаев. А тех редких случаях, когда будет вызов — не факт, что именно он окажется узким горлышком. Ну и наконец, если при каком-то невероятнейшем раскладе это случится, то оптимизация будет тривиальной. Я только не понимаю, зачем нам сейчас рассматривать эту экзотику, хогда разговор на уровне "что такое хорошо и что такое плохо".
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 14.03.2019 14:08 rg45 . Предыдущая версия . Еще …
Отредактировано 14.03.2019 14:06 rg45 . Предыдущая версия .
Отредактировано 14.03.2019 14:05 rg45 . Предыдущая версия .
Re[6]: range based for - первый/последний?
От: andrey.desman  
Дата: 14.03.19 14:04
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Дело не в этом.

BFE>Вот такая конструкция не работает:
BFE>
BFE>  int i1 = 1;
BFE>  int i2 = 2;
BFE>  auto [a, b] = std::tuple{i1, i2};
BFE>

BFE>А жаль.

Ибо потому что через тупл надо, потому что тут присваивание, а значит {} описывает initializer_list вместо конструктора. Были бы разные типу у it и i2, то даже до этого не дошел бы.
Re[5]: range based for - первый/последний?
От: B0FEE664  
Дата: 14.03.19 14:14
Оценка:
Здравствуйте, rg45, Вы писали:

BFE>>Затем, чтобы избежать вызова std::end(v) на каждую проверку условия цикла.

R>Меня тут давеча в преждевременной оптимизации упрекали.
Это был не я.

R>Так вот это оно самое.

Да неужели? А писать ++it вместо it++ — тоже преждевременная оптимизация?
И каждый день — без права на ошибку...
Re: range based for - первый/последний?
От: Skorodum Россия  
Дата: 14.03.19 14:21
Оценка:
Здравствуйте, Marty, Вы писали:

M>Для нового range-for'а есть какой-нибудь вариант?

С помощью std::reverse_iterator и небольшой шаблонной магии:
#include <iterator>
#include <string>
#include <iostream>
 
template <typename T>
struct reversion_wrapper { T& iterable; };
 
template <typename T>
auto begin (reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
 
template <typename T>
auto end (reversion_wrapper<T> w) { return std::rend(w.iterable); }
 
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { iterable }; }
 
int main (int, char**)
{
    std::string foo("Hello World!");
    for (const auto& it: reverse(foo))
        std::cout << it;

    // Для выводна в обратном порядке, наверное, проще будет std::reverse_copy
    std::reverse_copy(foo.begin(), foo.end(), std::ostream_iterator<int>(std::cout));
    return 0;
}
reverse_iterator reverse_copy
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.