Как заставить компилятор C ++ следовать тому же приоритету, ассоциативности и порядку оценки, которые C # имеет в этом операторе присваивания?

Рассмотрим следующий фрагмент кода:

int x = 1;
int y = 2;
y = x + (x = y);

Когда это выполняется в C #, переменным в конечном итоге присваиваются следующие значения:

х = 2

у = 3

С другой стороны, когда то же самое выполняется в C ++, переменные заканчиваются следующим образом:

х = 2

у = 4

Очевидно, компилятор C ++ использует разные старшинство, ассоциативность а также порядок оценки правила, чем C # (как объяснено в эта статья Эрика Липперта).

Итак, вопрос в следующем:

Можно ли переписать оператор присваивания, чтобы заставить C ++ оценить то же, что и в C #?

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

-3

Решение

Да, это действительно возможно.

x = (y+=x) - x;

Так просто.

4

Другие решения

Можно ли переписать оператор присваивания, чтобы заставить C ++ оценить то же, что и в C #?

Да. Чтобы уточнить, правило в C # состоит в том, что большую часть времени левая сторона выражения полностью оценивается перед правой стороной. Таким образом, C # гарантирует, что оценка x слева от + происходит до того, как побочный эффект x = y на правой стороне. C ++ не дает этой гарантии; составители могут не согласиться со значением этого выражения.

(Задача: я сказал «больше всего» по причине. Приведите пример простого выражения в C #, где побочный эффект слева выполняется после побочного эффекта справа.)

Я знаю, что это можно переписать, разбив назначения на две отдельные строки

Правильно. Вы хотите иметь утверждение, которое имеет два побочных эффекта: увеличить y на исходное значение x и присвоить исходное значение y x. Таким образом, вы могли бы написать это как

int t = y;
y = y + x;
x = t;

Но:

цель состоит в том, чтобы сохранить его в одной строке.

Я предполагаю, что под «линией» вы подразумеваете «утверждение». Хорошо. Просто используйте оператор запятой.

int t = ((t = y), (y = y + x), (x = t));

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

Дополнительный кредит: Сколько скобок в этом утверждении требуется?


Супер бонус: что если мы не хотим использовать запятую? Мы можем использовать другие операторы в качестве операторов последовательности.

int t = ((t = y) & 0) || ((y = y + x) & 0) || (x = t);

Мы выполняем слева от ||и оказывается ложным, поэтому мы выполняем правую часть и так далее.

Так же, ((expr1) & 0) ? 0 : (expr2) гарантирует вам, что expr1 работает до expr2,

В основном, здесь вам нужна гарантия того, что ряд подвыражений произойдет в определенном порядке. Найдите «точки последовательности», чтобы увидеть, какие операторы в C и C ++ создают точки последовательности; Вы можете использовать их для последовательности выражений, отсюда и название.

3

Вы могли бы написать:

int x = 1;
int y = 2;
y = std::exchange(x,y) + y;

Но крайне не рекомендуется. Вы даже должны прекратить просмотр и подумать об этой простой операции.

1
По вопросам рекламы [email protected]