Здравствуйте, pkl, Вы писали:
pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:
pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
pkl>}
pkl>
pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера. pkl>Цикл помирает как только исчерпается самый мелкий контейнер. pkl>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?
Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.
Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:
R>Как раз вундерфалинг и получается: целых 29 строк нечитаемого птичьего языка с кучей особенного синтаксиса, typeinfo и большого количества сущностей. R>Абсолютный антипаттерн во все времена — делаем охрененно сложно и жрущее процессор, только чтобы влепить что-то в неподходящий для этого оператор языка. R>Жесть!
Ты так возмущаешься, как-будто я предлагаю этот код писать каждый раз. Во-первых, все что идет до строки №46 уже есть в boost, в каком-то виде. Не нравится boost — пожалуйста, написал один раз и пользуйся, сколько влезет. В этом случае от всего примера только функция main и остается. Основной моей мыслью было то, что не не нужно каждую школьную задачку встраивать в язык.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.
R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:
Когда такое встречается в проекте, который достался в поддержку, и срочно необходимо что-то изменить, очень хочется найти этого любителя вые....ться, и популярно обьяснить ему принцип KISS
Здравствуйте, pkl, Вы писали:
pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера. pkl>Цикл помирает как только исчерпается самый мелкий контейнер.
такой пробег обычно делается через zip. на плюсах это многословно можно сделать в бусте
слово zip можно встретить в хаскеле и питоне
расширять синтаксис C++ для zip кажется оверкилом, лучше что-то такое иметь в stl
Здравствуйте, pkl, Вы писали:
GC>>for( auto i1 : a, auto i2 : b, auto i3 : c) { pkl>Не логично. У вложенных другая семантега.
Имею в виду, что для синтаксиса выше логичнее использовать вложенную семантику, а не zip.
Здравствуйте, rg45, Вы писали:
R>Это делается элементарно и смысла тащить это в стандарт лично я не вижу. Тут уже вспоминали про zip. Еще можно было бы вспомнить некоторые полезности из boost, такие как iterator_range, iterator_facade, iterator_adaptor.
R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:
R>https://ideone.com/HkybcL
"Лишних" операций копирования/перемещения такой Zip не осуществляет (кроме как в случае передачи временного объекта, для которого производится перемещение, чтобы продлить время его жизни до конца range based for loop, использующего Zip). Это может быть продемонстрировано с помощью вспомогательного класса Array:
Здравствуйте, rg45, Вы писали:
R>Но сейчас я хочу показать, как достаоточно просто эта задача решается средсдтвами самого языка, без использования всего перечисленного:
R>https://ideone.com/HkybcL
Объект, возвращаемый make_zip_range, должен обеспечивать пролонгацию времени жизни временных объектов, переданных на вход make_zip_range, до момента завершения range-based for loop. Иначе может произойти страшное.
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, rean, Вы писали:
R>>Работает правильно.
U>Прочитай исходное сообщение внимательнее, чтобы понять как оно должно работать
По-моему, этой фразой вы отвечаете на вопрос о том, стоит ли вносить такое изменение в стандарт. Если оно настолько интуитивно непонятно, что нужно читать спеку, то внесение этой фичи в стандарт весьма сомнительно.
Здравствуйте, rean, Вы писали:
pkl>>>Можно ли это сделать уже щас без вундервафлинга? R>.. R>> using reference = std::tuple<decltype(*std::declval<T>())...>;
R>Как раз вундерфалинг и получается: целых 29 строк нечитаемого птичьего языка с кучей особенного синтаксиса, typeinfo и большого количества сущностей.
И где здесь typeinfo?
Здравствуйте, rean, Вы писали:
R>rg45, никто не умаляет ваши возможности писать шаблонный код. Они действительно впечатляют. Но все же существует промышленный C++, где люди не соревнуются в своем умении щеголять перед толпой, а создают программы, какие надо поддерживать и развивать. Я когда пришел сюда в форум, если често, просто офигел насколько все запущено с этим, судя по последним темам. А еще когда увидел эту тему про идею для стандарта, так совсем глаза на лоб полезли — потому что такие вот стремления людей к синтаксическому сахару все-же поддерживаются общим «безумием толпы». Придет кто-нибудь сюда и подумает, что C++ — это где-то в облаках, метапрограмирование, последние версии стандарта и прочие небесные технологии. А в реальности приходится возиться совсем с другими вещами.
Я удивляюсь, как тебе удается находить в моих сообщениях смысл, которого там нет, а потом еще и спорить по этому поводу. Еще раз, это был просто мой ответ на вопрос топикстартера: я выразил мнение, что не нужно встраивать в язык возможность, которую без труда можно реализовать в любой прикладной библиотеке. А мой пример — это всего лишь крошечный пруф того, что все это действительно легко делается встроенными средствами языка, даже без каких-либо внешних библиотек. Где ты там увидел, чтоб я предлагал использовать этот код в проекте, для меня остается загадкой
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rean, Вы писали:
R>Лично я понимаю интерес программистов к этим вещам. Все-же гребень технологий, и это уводит от рутины, да и просто интересно с точки зрения мужчины — покорять сложности и доказывать себе и другим что можешь. Но, увы, из ваших текстов складывается впечатление, что то что вы пишите — так и надо делать.
гребнем это было году эдак в 2001.
сейчас это просто средство для упрощения клиентского кода.
если кому то хочется писать на C++ с классами без RAII и прочего, то это не значит что всем остальным этого тоже достаточно.
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
pkl>}
pkl>
pkl>На каждой итерации i1, i2, i3 имеет очередное значение из соответствующего контейнера. pkl>Цикл помирает как только исчерпается самый мелкий контейнер.
Увидев такую запись, интуитивно я бы предположил, что такой цикл переберет все возможные комбинации элементов из 3-х контейнеров, а не будет двигаться параллельно сразу по трем.
Здравствуйте, pkl, Вы писали:
pkl>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?
Ты можешь им предложить это лично. Улучшения так себе, если честно и мне кажется это можно решеть придумав класс-обёртку контейнер-контейнеров.
Здравствуйте, pkl, Вы писали:
pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:
Логично было бы сделать как три вложенных цикла
for( auto i1 : a, auto i2 : b, auto i3 : c) {
}
развернув в
for(auto i1 : a) {
for(auto i2 : b) {
for(auto i3 : c) {
}
}
}
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, pkl, Вы писали:
pkl>>Можно ли это сделать уже щас без вундервафлинга?
NB>можно. получится что-то вроде zip_iterator
Это несколько более жопно. Хочется в 1 строку встроенными средствами, не дописывая своих херен.
Здравствуйте, GhostCoders, Вы писали:
GC>Здравствуйте, pkl, Вы писали:
pkl>>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно: GC>Логично было бы сделать как три вложенных цикла
GC>
GC>for( auto i1 : a, auto i2 : b, auto i3 : c) {
GC>}
GC>
GC>развернув в GC>
GC>for(auto i1 : a) {
GC> for(auto i2 : b) {
GC> for(auto i3 : c) {
GC> }
GC> }
GC>}
GC>
Здравствуйте, GhostCoders, Вы писали:
GC>Здравствуйте, pkl, Вы писали:
GC>>>for( auto i1 : a, auto i2 : b, auto i3 : c) { pkl>>Не логично. У вложенных другая семантега. GC>Имею в виду, что для синтаксиса выше логичнее использовать вложенную семантику, а не zip.
Не понял почему логичнее. Вы сначала бежите по внутреннему, потом делаете шаг по внешнему и заново бежите по внутреннему.
Здравствуйте, rean, Вы писали:
R>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?
Здравствуйте, rean, Вы писали:
pkl>>Жопа ли это? Я тупой наркоман? Можно ли это сделать уже щас без вундервафлинга?
R>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?
Ну поменяли же стандарт, введя range based loops, хотя можно было обойтись итераторами.
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, pkl, Вы писали:
pkl>>Не понял почему логичнее.
U>потому что это самая первая ассоциация, когда видишь такой код. похоже на list comprehension: https://en.wikipedia.org/wiki/List_comprehension
У чувака код работает не так: он много раз бегает по 3, меньше раз бегает по 2 и один раз бегает по 1.
Это совсем не то, что делал мой код из первого поста.
Здравствуйте, Constructor, Вы писали:
C>Объект, возвращаемый make_zip_range, должен обеспечивать пролонгацию времени жизни временных объектов, переданных на вход make_zip_range, до момента завершения range-based for loop. Иначе может произойти страшное.
Ну это можно. Я открою страшную тайну: в этом эскизе это не единственный дефект
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Nuzhny, Вы писали:
R>>А три итератора и использование обычного while цикла и трех проверок на end() уже не C++? Надо обязательно стандарт менять?
N>...или 1 индекс.
Индекс не всегда годится, в общем случае надо итераторы.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, rean, Вы писали:
R>Да вообще не надо такое писать. Разве что ради стеба.
Этот пример, на самом деле состоит из двух частей. Первая часть — библиотечная — она пишется один раз, тестируется и спокойно лежит и ждет своего часа. Это как разумная альтернатива тому, чтоб встраивать такую возможность в язык, как это предлагает ТС. И когда она понадобится, мои программы будут получаться вот такими:
auto ia = a.begin();
auto ib = b.begin();
auto ic = c.begin();
for (;;) {
bool in_a = ia != a.end();
bool in_b = ib != b.end();
bool in_c = ic != c.end();
if (!(in_a || in_b || in_c)) break;
if (in_a)
std::cout << *ia;
else
std::cout << "-";
if (in_b)
std::cout << ", " << (*ib).c_str();
else
std::cout << ", -";
if (in_c)
std::cout << ", " << *ic;
else
std::cout << ", -";
std::cout << std::endl;
if (in_a) ++ia;
if (in_b) ++ib;
if (in_c) ++ic;
};
Если тебе твоя программа нравится больше, пожалуйста, я тебе ничего не навязываю. Мне же, извини, это напоминает рецепт какого-то борща.
R>Оно скорей всего у меня даже не откомпилируется на VC++, а boost так это еще + 300 мегабайт в проект.
Спокойно компилируется, можешь проверить.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Михaил, Вы писали:
М>Когда такое встречается в проекте, который достался в поддержку, и срочно необходимо что-то изменить, очень хочется найти этого любителя вые....ться, и популярно обьяснить ему принцип KISS
А я где-то предлагал делать такое в проекте? Сколько раз нужно повторить любителям поумничать вот это
Здравствуйте, pkl, Вы писали:
pkl>Есть 3 контейнера: a, b, c. Хочу запустить 1 range-цикл по ним всем одновременно:
pkl>
pkl>for( auto i1 : a, auto i2 : b, auto i3 : c) {
pkl>}
pkl>
1) IMHO это не надо вообще
2) Если уж кому-то правда надо, то логичнее было бы записывать как-то так:
for( auto [i1, i2, i3] : std::tie( a, b, c ) ) {
}
3) Я не проверял, но есть такое чувство, что если делать на версии языка, которая уже умеет автоматически разбирать кортежи, то для того, что бы заработал синтаксис вроде того, что сверху, достаточно написать шаблонные begin и end для кортежа контейнеров/диапазонов...
Как вариант, можно написать функцию zip, которая возвращает какой-то специальный zip_t, в котором есть кортеж контейнеров и реализация соотв. итератора, и от которого есть функции begin и end
Можно, кстати, ещё и других комбинаторов понаписать.
будет как-то так:
for(auto [ia, ib, ic] : zip( a, b, c ) ) {
// то, что просил ТС
}
for(auto [ia, ib, ic] : zip( a, zip_optional(b), c ) ) {
// то, что просил ТС, но ib -- std::optional и конец контейнера b не заканчивает последовательность
}
for(auto [ia, ib, ic] : all_combinations( a, b, c ) ) {
// то, что не просил ТС
}
// и т. д...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском