4 Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified.53) Between the previous
and next sequence point a scalar object shall have its stored value modified at most once by the evaluation
of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.
The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
expression; otherwise the behavior is undefined. [Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
—end example]
Короче, обьясняю по-простому. Компилятор, разбирая выражение, строит дерево разбора. В дальнейшем, он должен выбрать некоторый порядок обхода этого дерева (усилить отношение частичного порядка до линейного). Вообще говоря, это можно сделать многими разными способами. Более того, здесь таится опасность комбинаторного взрыва, в том смысле, что число всех вариантов обхода растет экспоненциально. Так вот, если для двух таких вариантов вы получите функционально не эквивалентную последовательность операций вы проиграли. И даже не потому, что стандарт относит это к unspecified behavior, хрен с ним со стандартом. А потому, что результат вычисления такого выражения вы отдали на произвол компилятору. Т.е. вполне возможно, что где-нибудь после нескольких лет успешной работы (или даже после нескольки часов просто переключением опций компилятора) вы радикально измените свою программу и будете ооооочень долго искать, где же собака порылась. Можно было бы, конечно, договорится применять side-effectы в определённом месте, но это может войти в противоречие с аппаратурой, поскольку, например, некоторые процессоры прекрасно умеют делать авто-инкремент в регистрах. С анализом таких подвохов в compile-time тоже проблема, поскольку см. выше.
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, Шахтер, Вы писали:
ME>[]
Ш>>Ну так придумайте инкапсуляцию для операторов как свойство языка. Это было бы, по-моему, куда более продуктивно.
ME>Все уже придумано: boost::lambda.
ME>Слышал, что предлагают добавить лямбда-выражения в core language.
Вот если в core language, то это в coreне меняет дело.
Здравствуйте, Шахтер, Вы писали:
Ш>Здравствуйте, Юнусов Булат, Вы писали:
ЮБ>>Здравствуйте, Аноним, Вы писали:
А>>>Булат, Вы промахнулись в этой строчке: А>>>
Здравствуйте, Шахтер, Вы писали:
Ш> Between the previous and next sequence point a scalar object shall have Ш> its stored value modified at most once by the evaluation of an expression. Ш> Furthermore, the prior value shall be accessed only to determine Ш> the value to be stored. The requirements of this paragraph shall be met for Ш> each allowable ordering of the subexpressions of a full expression; Ш> otherwise the behavior is undefined. Ш> [Example: Ш> i = v[i++]; // the behavior is unspecified Ш> i = 7, i++, i++; // i becomes 9 Ш> i = ++i + 1; // the behavior is unspecified Ш> i = i + 1; // the value of i is incremented Ш> —end example]
Ш> стандарт относит это к unspecified behavior
Хуже: undefined.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Шахтер, Вы писали:
Ш>> Between the previous and next sequence point a scalar object shall have Ш>> its stored value modified at most once by the evaluation of an expression. Ш>> Furthermore, the prior value shall be accessed only to determine Ш>> the value to be stored. The requirements of this paragraph shall be met for Ш>> each allowable ordering of the subexpressions of a full expression; Ш>> otherwise the behavior is undefined. Ш>> [Example: Ш>> i = v[i++]; // the behavior is unspecified Ш>> i = 7, i++, i++; // i becomes 9 Ш>> i = ++i + 1; // the behavior is unspecified Ш>> i = i + 1; // the value of i is incremented Ш>> —end example]
Ш>> стандарт относит это к unspecified behavior
ПК>Хуже: undefined.
В таком случае попрошу поподробнее. Почему в коментария написано unspecified (опечатка?). В чем разница между unspecified и undefined.
Только не надо отсылать к стандарту. У старенького дяди Шахтёра мозгА в этом стандарте не всё понимает.
И ещё. Раз у нас тут такие знатоки стандарта. В этом коде насколько оправдан вызов transform. Дело в том, что он читает данные из того же массива, в который пишет. Стандарт вроде не определяет, в каком точно порядке transform работает. Может он откладывает запись, например. Или вообще едет сверху вниз (это конечно маловероятно, но возможно). Или запускает несколько потоков на многопроцессорной системе.
Effects: Assigns through every iterator i in the range [ result, result + ( last1 first1))
a new corresponding value equal to op(*( first1 + (i result))
or
binary_op(*( first1 + (i result),
*( first2 + (i result))).
Requires: op and binary_op shall not have any side effects.
( Напомню свою сигнатуру: #define FOR_EACH_(Decl, First, Last) )
Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.
Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.
F>Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.
F>Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.
Ну я наоборот считаю end() более простой операцией — так как это же fake'овый объект как правило и его проще построить.
Здравствуйте, lboss, Вы писали:
L>Здравствуйте, folk, Вы писали:
F>>Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.
F>>Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.
L>Ну я наоборот считаю end() более простой операцией — так как это же fake'овый объект как правило и его проще построить.
И на это есть ответ
Я рассматривал подобный монолитный вариант, но мне подумалось что я смогу повторно использовать элементарные wrap/unwrap для другой задачи, так что в результате сделал на них и поместил их в namespace util (а не в _foreach как в опубликованном варианте).
А вообще это правильно, чем больше удается вынести из мароса в шаблон, тем лучше. В скопе цикла находятся меньше скрытых макросом переменных.
Здравствуйте, Шахтер, Вы писали:
Ш>>> <... цитата из 5/4 ...>
Ш>>> стандарт относит это к unspecified behavior
ПК>> Хуже: undefined.
Ш> В таком случае попрошу поподробнее. Ш> Почему в коментария написано unspecified (опечатка?).
Да, опечатка, даже defect report имеется: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#351
Ш> В чем разница между unspecified и undefined. Только не надо отсылать Ш> к стандарту. У старенького дяди Шахтёра мозгА в этом стандарте не всё Ш> понимает.
ЮБ>>Чем функторы то так не нравятся, рульно же когда цикл в одном месте а алгоритм в другом — нафига обртно все в кучу упихивать то?
Ш>Доказывать с пеной у рта не буду, но по-моему не рульно. Потому что расщепляет некую целостность на два фрагмента, далеко расположенных по тексту друг от друга.
зато использование таких супер макросов как у тебя чрезвычайно рульно..
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
A reference to type ``cv1 T1'' is initialized by an expression of type ``cv2 T2'' as follows:
If the initializer expression
— is an lvalue (but is not a bit-field), and ``cv1 T1'' is reference-compatible with ``cv2 T2,'' or
— has a class type (i.e., T2 is a class type) and can be implicitly converted to an lvalue of type ``cv3 T3,'' where ``cv1 T1'' is reference-compatible with ``cv3 T3'' *
[Footnote: This requires a conversion function (class.conv.fct) returning a reference type. --- end foonote]
Не уверен что правильно понял. Наше rvalue класс-типа может быть неявно преобразовано в lvalue?
Здравствуйте, folk, Вы писали:
F>И на это есть ответ F>Я рассматривал подобный монолитный вариант, но мне подумалось что я смогу повторно использовать элементарные wrap/unwrap для другой задачи, так что в результате сделал на них и поместил их в namespace util (а не в _foreach как в опубликованном варианте).
Не понял аргументации — ибо для практически любой другой задачи проще итераторами пользоваться всё-таки... по моему...
F>А вообще это правильно, чем больше удается вынести из мароса в шаблон, тем лучше. В скопе цикла находятся меньше скрытых макросом переменных.
Вообще-то, по моему, главный принцип (или заслуга) данного подхода — это работающий break, и ясность реализации...