Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.85/13: Рейтинг темы: голосов - 13, средняя оценка - 4.85
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99

Что-то не так с transform?

17.11.2016, 17:19. Показов 2807. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
transform требует итераторы ввода и делает что-то такое:

C++
1
2
3
4
5
6
7
8
9
template<class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first,
                   UnaryOperation unary_op)
{
    while (first1 != last1) {
        *d_first++ = unary_op(*first1++);
    }
    return d_first;
}
И видим здесь:
*first1++

То есть, смещаемся к следующему элементу контейнера, БЕРЁМ СТАРОЕ ЗНАЧЕНИЕ ИТЕРАТОРА, РАЗЫМЕНОВЫВАЕМ... То же самое слева от присваивания. Но: если значение итератора ввода увеличено на единицу, нет никаких гарантий, что его можно
разыменовать по предыдущему значению (с) Прата. Это что же, возможная реализация алгоритма transform с cppreference - неправильная? Или я что-то не так понимаю?
4
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
17.11.2016, 17:19
Ответы с готовыми решениями:

CSS transform, transition отображаются в Opera не так как в IE
Приветствую всех! Столкнулся с тем что в IE это работает, а в Opera, при наведении на ссылку она вначале увеличивается, а потом сразу...

В Access был TRANSFORM, а что в MS SQL Server?
Для построения перекрестного запроса (таблицы) в Access можно было использовать TRANSFORM и получать, что данные некоторого столбца...

Unity: Объясните мне, как работает функция transform. Что такое Vector3?
Кто нибудь, Объясните мне как работает функция transform что такое Vector3 и как в 2D игре при нажатии кнопки заставить объект...

38
7 / 11 / 0
Регистрация: 01.08.2012
Сообщений: 99
17.11.2016, 20:37  [ТС]
Студворк — интернет-сервис помощи студентам
Смысл: нельзя сохранять предыдущее значение итератора.
Как обеспечить: не использовать предыдущее значение итератора.
Каковы могут быть примеры?
На постинкремент это не распространяется, хорошо. Тогда как он реализован? Приведён, насколько понимаю, псевдокод.

Да так, ни о чём. Если надо объяснять, то не надо объяснять.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 20:39
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Можете пример привести?
Привести пример чего?
Ответьте на предыдущий вопрос.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 20:45
Цитата Сообщение от castaway Посмотреть сообщение
Смысл: нельзя сохранять предыдущее значение итератора.
Как обеспечить: не использовать предыдущее значение итератора.
И?

Об этом и вопрос! Формально выражение *it++ означает *(it++) и в случае перегруженных операторов * и ++ производится сохранение и использование предыдущего значения итератора после того, как получен инкрементированный итератор.

С точки зрения буквальной интерпретации этого нельзя делать для итераторов класса input iterator. С такими итераторами формально нельзя делать *it++.

Однако в спецификации языка для этих целей сделано специальное замечание, которое добавляет спеициальную трактовку для выражения *it++ в случае input iterator. А именно, такое выражение должно быть экаивалентно

C++
1
2
3
{ T tmp = *r;
++r;
return tmp; }
4
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 20:47
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
в случае перегруженных операторов * и ++ производится сохранение и использование предыдущего значения итератора после того, как получен инкрементированный итератор.
Где производится? Я не вижу.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 20:52
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Однако в спецификации языка для этих целей сделано специальное замечание, которое добавляет специальную трактовку для выражения *it++ в случае input iterator. А именно, такое выражение должно быть эквивалентно

C++
1
2
3
{ T tmp = *r;
++r;
return tmp; }
(см. 24.2.3 Input iterators)

Таким образом исходный код transform корректен, но именно из-за этой специальной обработки выражения *it++ для input iterators.

Общая проблема поднятая kozlik_kozlik действительно имеет место и вопрос задан совершенно справедливый. Ответ на этот вопрос: спецификация стандартной библиотеки содержит "костыль", специально предназначенный для того, чтобы такие случаи работали правильно.

Добавлено через 1 минуту
Цитата Сообщение от castaway Посмотреть сообщение
Где производится? Я не вижу.
Как это где? Внутри реализации постфиксного ++. Постфиксный ++ возвращает старое значение итератора, после чего инкрементирует исходное значение. После этого использовать старое значение уже нельзя. А *it++ посылает это старое значение в оператор *. Отсюда и вопрос.
4
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 20:54
Цитата Сообщение от kozlik_kozlik Посмотреть сообщение
Правильно, если старожил ошибается, это простительно. А новичку можно и нахамить за вопрос. Действительно, чего церемониться.
kozlik_kozlik, вы ответите к чему это было сказано или это клевета?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 21:05
Обратите, кстати, внимание, что спецификация языка разрешает использование только двух типов выражений с постфиксным инкрементом для input iterators:

* (void)r++ - equivalent to (void)++r
* *r++ - определено специальным образом (см. выше)

То есть на самом деле постфиксный ++ формально бесполезен для input iterators - его результат все равно запрещено использовать. Но ради полезной идиомы *r++ было принято решение внести в спецификацию такой "костыль". Фактически *r++ для input iterators - это атомарная операция со своим индивидуальным определением. Она не распадается на независимые * и ++.

Вопрос kozlik_kozlik не просто правильный, а весьма интересный. Я помню, что читал когда-то что-то на эту тему, но мимоходом не до конца понимал, зачем это нужно. А оказывается вот оно что.
1
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
17.11.2016, 21:10
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Постфиксный ++ возвращает старое значение итератора, после чего инкрементирует исходное значение.
Наоборот, сначала икрементирует, потом возвращает старое, которое было сохранено в промежутке

Я в принципе так и думал, что последовательность этих 3 операторов как то должна быть обговорена. Сначала подумал про изменение контейнера. Но, тут, как уже сказал TheCalligrapher, об этом сказано явно в стандарте. Если найти причину, почему так сделано, то все станет понятно.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 21:15
Цитата Сообщение от Toshkarik Посмотреть сообщение
Наоборот, сначала икрементирует, потом возвращает старое, которое было сохранено в промежутке
Да, я неточно выразился, под "возвращает старое" я хотел сказать "сохраняет старое значение для последующего возвращения".
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 21:56
TheCalligrapher, разыменование итератора что даёт?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 22:04
Цитата Сообщение от castaway Посмотреть сообщение
TheCalligrapher, разыменование итератора что даёт?
Хм... Разыменование итератора даёт нам то значение, на которое итератор ссылается.

(Но к чему это здесь?)
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 22:08
Это я к тому, что вы говорите о "старом" и "новом" значении итератора, хотя этот, уже известный вам кусок кода:
C++
1
2
3
value_type x = *i;
++i;
return x;
говорит что нет никакого "старого" итератора.
Есть значение итератора, а есть значение на которое он ссылается.
0
59 / 54 / 34
Регистрация: 18.04.2014
Сообщений: 122
17.11.2016, 22:12
TheCalligrapher, не понимаю почему он сначала инкрементирует, а потом возвращает старое, если постфиксная операция должна увеличивать итератор после вычисления выражения. Я не читал стандарт, но мне казалось что возвращается текущее значение, а затем увеличивается, и таким образом нет возвращения предыдущего значения итератора.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 22:14
Цитата Сообщение от castaway Посмотреть сообщение
говорит что нет никакого "старого" итератора.
Ну так я о том и говорю, что в стандартной билиотеке выражению *r++ для input iterator r придано специальное особенное значение, выражаемое вашим куском кода.

При этом в общем случае выражение *r++ такой семаники не имеет даже отдаленно. В общем случае такое выражение имеет семантику

C++
1
2
iterator_type old_r = r++;
return *old_r;
Вопрос ТС потому и возник, что ТС не знал, что в спецификацию языка для input iterator вписан специальный "костыль", переиначивающий трактовку *r++ именно и только для input iterators.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
17.11.2016, 22:20
TheCalligrapher, это удивительно:
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
C++
1
{ T tmp = *r; ++r; return tmp; }
А чем плохо:
C++
1
2
3
4
container<T>::iterator tmp_it = r;
r++;
T val = *tmp_it; 
//----
Временный итератор должен скопировать "предыдущее" значение итератора. Почему инкрементирование должно повлиять на полученный tmp_it ?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 22:37
Цитата Сообщение от IGPIGP Посмотреть сообщение
Почему инкрементирование должно повлиять на полученный tnp_it ?
Потому что так сказно в спецификации input iterator.

Input iterator предназначен для итерования "однопроходных" входных последовательностей. За таким итератором может скрываться поток ввода с клавиатуры или чтения с накопителя на манитной ленте. После того, как вы прочитали данные, вы уже либо принципиально не можете прочитать их снова (нельзя заставить пользователя напечатать еще раз то, что он печатал ранее), либо это слишко дорого (дорого перематывать магнитную ленту назад), либо вы просто настаиваете на однопроходной природе алгоритма.

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

Добавлено через 9 минут
Цитата Сообщение от Mathist Посмотреть сообщение
не понимаю почему он сначала инкрементирует, а потом возвращает старое, если постфиксная операция должна увеличивать итератор после вычисления выражения.
Не должна. В спецификации префиксного и постфиксного ++ нет никаких намеков на то, в какой момент происходит модификация операнда.

Спецификации префиксного и постфиксного говорят, что префиксный ++ возвращает новое значение операнда, а постфиксный ++ возвращает старое значение операнда. И все.

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

Поэтому ваше предположение, что постфиксный ++ должен "увеличивать итератор после вычисления выражения" совершенно не обосновано. Ничего подобного никогда в спецификации постфиксного ++ не было.
3
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
17.11.2016, 22:42
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Потому что так сказно в спецификации input iterator.
Спасибо, теперь понятно.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
17.11.2016, 23:02
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
При этом в общем случае выражение *r++ такой семаники не имеет даже отдаленно.
Увы, в обсуждаемой теме не общий случай.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13210 / 6843 / 1824
Регистрация: 18.10.2014
Сообщений: 17,306
17.11.2016, 23:51
Цитата Сообщение от castaway Посмотреть сообщение
Увы, в обсуждаемой теме не общий случай.
Так поэтому-то вопрос ТС и появился, как я его понял. Input iterator - это весьма особенный случай. А реализация transform "почему-то" об этом не беспокоится и спокойно реализует свою функциональность так, как будто ничего особенного в input iterator нет.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.11.2016, 23:51

Что не так с кодом? ( пытаюсь понять, что не так? )
Есть исходный код. Hook, работает хорошо, но есть минус огромный - перестаёт писать в лог, при открытии программы\игры Фуллскрином. т.е...

И так, что не так с моим запросом на добавление записи в таблицу?
$sql = 'INSERT INTO product ' . '(name, code, price, category_id, brand, availability,' . 'description,...

Как сделать так что я мог умножать не на два числа а на 3,4,5 и так далее?
Вот код: #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; int main(){ float a,c; char b; skip: ...

сегодня так можно сказать праздник так что...
простите меня за все пожалуйста!!!

Что в коде ни так? while не работает так, как ожидаю
Написанный код, как я думаю, должен выдавать цифры от 0 до 1000, столбиком. Но выдает начиная от 702 до 1000. Что ни так понимаю, где...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу))) Критические ошибки, мешающие компиляции и. . .
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата) Этот документ предназначен для того, чтобы новый чат Claude мог продолжить работу без необходимости заново разбираться в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru