Вызов функции-инварианта аргумента-перестановки f (i ++, i ++) - PullRequest
0 голосов
/ 20 сентября 2018

Предположим, у меня есть функция foo(x, y, z), которая инвариантна относительно всех перестановок своих аргументов.У меня также есть итератор it, так что итераторы it, it + 1 и it + 2 могут быть разыменованы.

Можно ли писать

... = foo(*it++, *it++, *it++);  // (1)

вместо

... = foo(*it, *(it + 1), *(it + 2));  // (2)

?

Насколько я понимаю, технически это правильно с C ++ 17 из-за (цитируя cppreference.com и учитывая, что it может быть необработанным указателем)

15) При вызове функции вычисления значений и побочные эффекты инициализации каждого параметра имеют неопределенную последовательность относительно вычислений значений и побочных эффектов любого другого параметра..

Порядок вычисления аргументов функции не определен, но для foo() порядок не имеет значения.

Но является ли это приемлемым стилем кодирования?С одной стороны, (1) приятно симметричен и подразумевает, что foo имеет такую ​​инвариантность, а (2) выглядит несколько уродливо.С другой стороны, (1) немедленно поднимает вопрос о его правильности - тот, кто читает код, должен проверить описание или определение foo, чтобы проверить правильность вызова.

Если тело foo() невелико, и инвариантность очевидна из определения функции. Примите ли вы (1)?

(Возможно, этот вопрос основан на мнении. Но я не могу не задать его.)

1 Ответ

0 голосов
/ 20 сентября 2018

Вы правы, что в C ++ 17

foo(*it++, *it++, *it++);

не является неопределенным поведением.Как говорится в вашей цитате и как указано в [expr.call] / 8

Постфиксное выражение упорядочено перед каждым выражением в списке выражений и любым аргументом по умолчанию.Инициализация параметра, включая каждое связанное с ним вычисление значения и побочный эффект, определяется неопределенным образом по сравнению с любым другим параметром.

Каждый шаг упорядочен, поэтому у вас нет нескольких непоследовательных записей.Порядок вычисления аргументов функции все еще не определен в C ++ 17, так что это означает, что у вас просто неопределенное поведение (вы не можете знать, какой элемент передается каждому аргументу).

Пока ваша функция нене волнуйся об этом, тогда ты в порядке.Если порядок аргументов будет иметь значение, то вам придется использовать вашу вторую версию.


При всем этом я бы предпочел использовать

foo(*it, *(it + 1), *(it + 2));

, даже если порядокне имеет значенияЭто делает код обратно совместимым, и, по-моему, его легче рассуждать.Я предпочел бы видеть it += 3 в инкрементной части цикла for, а затем множественные приращения в вызове функции и никакого приращения в инкрементной части цикла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...