Оператор if
в следующем примере взят из старого проекта, который я пытаюсь построить снова. Мне жаль, что это не проверяемый образец в том смысле, что он не воспроизводит ошибку, он сам по себе отлично компилируется.
enum S { };
struct R {
S type, state;
double height;
};
int main ()
{
int rows;
S alive, rc;
double h;
R *r, *n;
// BEGIN
if ( (((r = n-1) ->type & rc) && h > r->height) ||
(((r = n+1) ->type & rc) && h > r->height) ||
(((r = n-rows)->type & rc) && h > r->height) ||
(((r = n+rows)->type & rc) && h > r->height) )
{
n->state = alive;
}
// END
}
Однако внутри проекта при той же компиляции (clang 3.3 без опций, кроме путей включения) это дает
warning: multiple unsequenced modifications to 'r' [-Wunsequenced]
(указывая на подвыражение r = n - 1
). Оператор if
(отмечен BEGIN-END
) внутри проекта идентичен, только типы переменных могут отличаться. Типы, определенные здесь, являются лишь грубыми приближениями, но я думаю, что они не имеют отношения к предупреждению. Я смог упростить выражение до
if( (r = n) || (r = n) ) //...
при этом предупреждение воспроизводится в проекте.
Насколько я понимаю, после оценки первого операнда операторов &&
, ||
(когда они не перегружены) есть точка последовательности. Поэтому я не могу объяснить предупреждение.
Если есть какие-либо идеи относительно формы выражения независимо от типов, это поможет.
ИЗМЕНИТЬ
Используя комментарии Вона Катона, я также обнаружил, что
if( ((r = n-1) ->type) || ((r = n+1) ->type) )
выдает предупреждение, а
if( bool((r = n-1) ->type) || bool((r = n+1) ->type) )
не. S
на самом деле является классом, который имитирует перечисление и имеет собственный базовый класс. Он имеет перегруженные побитовые операторы &
, |
и !
для маскирования, а также оператор неявного преобразования в базовый тип, которым в конкретном случае является size_t
. Я не знаю, насколько это поможет, но я сожалею, что не раскрыл более полную информацию с самого начала.
&&
и||
? Только встроенные операторы имеют гарантию последовательности. - person Vaughn Cato   schedule 02.04.2014operator&
, но предупреждение остается даже в упрощенном выражении без&
. Кроме того,r,n
— это указатели, поэтому я не думаю, что смогу перегрузить что-то еще. - person iavr   schedule 02.04.2014r
в проекте также необработанным указателем? - person Vaughn Cato   schedule 02.04.2014r
— это необработанный указатель.R
— это обычныйstruct
.S
на самом деле неenum
, а скорее класс-оболочкаenumeration
, который тогда был попыткой имитировать наличие моего собственного базового типа. - person iavr   schedule 02.04.2014R
фактически содержалаunion
(для информации, которая использовалась во взаимоисключающих моментах времени), ноtype,state,height
занимала разные позиции. Толькоheight
делил ту же позицию с другим участником вunion
. - person iavr   schedule 02.04.2014if( bool(r = n) || bool(r = n) )
и посмотрите, получите ли вы такое же предупреждение. - person Vaughn Cato   schedule 02.04.2014operator ||
, который каким-то образом вызывается, и приведение к bool позволяет избежать использования перегрузки. - person Vaughn Cato   schedule 02.04.2014|
и&
, но не уверен. Когда я попытаюсь снова, мне может сойти с рук трюк сbool()
, заменаS
на настоящийenum
с пользовательским базовым типом или что-то еще, что может появиться. Я рад, что уже есть обходной путь, потому что это действительно умное выражение, которое я не хотел бы менять. - person iavr   schedule 10.04.2014