Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Январь 09, 2021, 11:54



Название: Итераторные пары
Отправлено: Igors от Январь 09, 2021, 11:54
Добрый день

Не раз замечал что у любителей std преобладают имена из 3 букв. Но у меня-то нет
Код
C++ (Qt)
if (std::find(mUsedThresholds.begin(), mUsedThresholds.end(), tindex) != mUsedThresholds.end())
 mUsedThresholds.push_back(tindex);
 
Да еще и неправильно (контейнер может быть пустым). Дело не в том что мне, мол, "лень писать", но оно выглядит отвратно :'( Ф-ционала на копейку, текста на рупь.

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

Спасибо


Название: Re: Итераторные пары
Отправлено: Old от Январь 09, 2021, 12:48
Прошло неск лет как это обсуждали, может появились средства языка позволяющие обойтись без таких длинных соплей? (новые стандарты и все такое)
Да не нужны для этого никакие новые стандарты.
Разработчики, как правило, стараются спрятать стандартные контейнеры в классах, описывающих сущности предметной области и добавить удобные методы для их использования.
Код
C++ (Qt)
class Threshols
{
public:
   bool isContains( int val ) const
   {
       return std::find( mUsedThresholds.begin(), mUsedThresholds.end(), val ) != mUsedThresholds.end();
   }
 
   void append( int val )
   {
       if( !isContains( val ) )
           mUsedThresholds.push_back( val );
   }
 
private:
   std::vector<int> mUsedThresholds;
};
 
Заодно, когда надоест постоянно бегать по вектору для поиска, это позволит незаметно для остального кода проекта это оптимизировать.


Если делать как вы привыкли и все располагать в классе MainWindow, то всегда можно добавить шаблонную функцию isContains, тогда можно будет делать так:
Код
C++ (Qt)
if( !isContains( mUsedThresholds, tindex) )
 mUsedThresholds.push_back( tindex );
 

Но зачем вам об этом заморачиваться - копипастите и все.

Не раз замечал что у любителей std преобладают имена из 3 букв. Но у меня-то нет
Ну конечно... Вы то у нас о-го-го. Судя по вашим то темам. :)

Да еще и неправильно (контейнер может быть пустым).
Ну и что? Если контейнер пустой, то begin() == end(). Не переживайте за стандартные алгоритмы, они с этим справляются. :)
Но вы для верности всегда можете добавлять перед find - !mUsedThresholds.empty() &&
Тогда, читающие ваш код специалисты, сразу будут понимать с чем имеют дело.


Название: Re: Итераторные пары
Отправлено: RedDog от Январь 09, 2021, 18:37
а почему бы в данном примере std::set не заюзать?
тогда не нужно будет это длинное условие


Название: Re: Итераторные пары
Отправлено: Igors от Январь 10, 2021, 09:37
а почему бы в данном примере std::set не заюзать?
тогда не нужно будет это длинное условие
Не, ну выбор контейнера определяется др соображениями, они могут быть самыми разными.

Мда, похоже что "а воз и ныне там". Нормально было бы так
Код
C++ (Qt)
if (!mUsedThresholds.contains(tindex))
 mUsedThresholds.push_back(tIndex);
Кстати "обветшавшие" Qt контейнеры все это имеют: find, contaiins, indexOf и.т.п. А добиться того же великом оказывается не так уж просто. Напр
Код
C++ (Qt)
template<class T, class Val>
bool MyContains( const T & vec, Val val )
{
 return std::find(vec.begin(), vec.end(), val) != vec.end();
}
Это запросто сработает для мапы убивая ф-ционал. На мой взгляд лучше скромное
Код
C++ (Qt)
template<class T, class Val>
bool VecContains( const std::vector<T> & vec, Val val );
Ну и дублить если еще понадобится (напр для деки). Все равно хорошего впечатления не производит. "Костыль", а хотелось бы "ис каропки"


Название: Re: Итераторные пары
Отправлено: Old от Январь 10, 2021, 10:00
Это запросто сработает для мапы убивая ф-ционал.
Вам нужно лучше изучить инструмент, который вы пытаетесь использовать.
Для мапы код не скомпилируется (поэтому убийтсва функционала не последует :) ), итератор мапа при разименовании не дает валуе.
К тому же у мапа есть свой метод для этого.
Даже если в коде был вектор и его заменили на мап, то при первой же сборке возникнет ошибка и разработчик замент этот вызов на соответствующий метод мапа.

Код
C++ (Qt)
template<class T, class Val>
bool VecContains( const std::vector<T> & vec, Val val );
Это что, идентификаторы из 3 букв? :)
А где же "Но у меня-то нет", или тайный любитель std? :)


Название: Re: Итераторные пары
Отправлено: Igors от Январь 12, 2021, 11:44
Может симпатичнее оформить как namеspace и юзать так
Код
C++ (Qt)
if (std_ext::contains(mUsedThresholds, tindex)) ..
Вроде ничего, но вот как пресечь для мапы и др контейнеров имеющих свой (быстрый) find - хз. Правда и само std::find этого не делает


Название: Re: Итераторные пары
Отправлено: ksk- от Январь 12, 2021, 12:27
Возможно, не до конца понял суть вопроса. Но что насчёт https://en.cppreference.com/w/cpp/ranges (https://en.cppreference.com/w/cpp/ranges)?


Название: Re: Итераторные пары
Отправлено: Old от Январь 12, 2021, 13:24
но вот как пресечь для мапы и др контейнеров имеющих свой (быстрый) find - хз.
Что-бы было не "хз", нужно книжку почитать по c++. :)
Но можно и дальше на форуме решения клянчить. :)


Название: Re: Итераторные пары
Отправлено: Igors от Январь 14, 2021, 11:54
Возможно, не до конца понял суть вопроса. Но что насчёт https://en.cppreference.com/w/cpp/ranges (https://en.cppreference.com/w/cpp/ranges)?
Да "суть" тут "под каждым кустом" :) Просто хочется схлопнуть код что выглядит неопрятно. Неужели для этого надо иметь последний стандарт, освоить новую концепцию и.т.п? Ну как-то "неадекватно".

Что касается ranges - назрело давно, много было великов, один я даже приводил в "кладовой" (уничтожающая критика местных знатоков :)). Но как range поможет схлопнуть тот же std::find который тупо требует пару итераторов ?


Название: Re: Итераторные пары
Отправлено: ksk- от Январь 14, 2021, 12:16
Цитировать
Но как range поможет схлопнуть тот же std::find который тупо требует пару итераторов ?
https://en.cppreference.com/w/cpp/algorithm/ranges/find (https://en.cppreference.com/w/cpp/algorithm/ranges/find)


Название: Re: Итераторные пары
Отправлено: Igors от Январь 15, 2021, 12:00
https://en.cppreference.com/w/cpp/algorithm/ranges/find (https://en.cppreference.com/w/cpp/algorithm/ranges/find)
Боюсь что эта вещь не предназначена для моих скромных целей (компактный вызов). И это лишь неск конкретных ф-ций

Кстати интересно, а зачем нужна std::ranges::find, почему не обойтись std::find или в чем разница? Судя по примеру реализации, в std::invoke. Немного копнул, да, познавательно, и наверное "небесполезно". Но не вижу ни одного примера в своих проектах где в этом нужда. В общем, "беллетристика" :)


Название: Re: Итераторные пары
Отправлено: Авварон от Январь 24, 2021, 18:15
Вздох

Код:
const auto v = {4, 1, 3, 2};

if (auto result = ranges::find_if_not(v, is_even); result != v.end()) {
  std::cout << "First odd element in v: " << *result << '\n';
} else {
  std::cout << "No odd elements in v\n";
}


Название: Re: Итераторные пары
Отправлено: Igors от Январь 25, 2021, 16:03
Вздох
Вы не замечали что перевод устойчивых буржуйских словечек неизменно уродлив? Так зачем самому повторять эту ошибку? :) Хоть бы творчески переводили (по смыслу это  "эх")

Код:
const auto v = {4, 1, 3, 2};

if (auto result = ranges::find_if_not(v, is_even); result != v.end()) {
  std::cout << "First odd element in v: " << *result << '\n';
} else {
  std::cout << "No odd elements in v\n";
}
Не знаю можно ли (с новыми стандартами) записать v.begin/end, может в этом смысл? Но лаконичностью и выразительностью такой код точно не блещет (даже с калечным "v"). Так что нечего там (томно) вздыхать  :)


Название: Re: Итераторные пары
Отправлено: Авварон от Январь 25, 2021, 16:39
Код:
ranges::find_if_not(v, is_even);

против

Код:
ranges::find_if_not(v.begin(), v.end(), is_even);

я даже не знаю что короче

что вам не нравится? итератор? ну напишите функцию, которая возвращает range (например, ленивый findAll), будете писать

Код:
if (auto result = findAll(v, is_even); !ranges::empty(result)) {
// do smth
}