Имеет ли перегруженный побитовый оператор или оператор (‘|’) четко определенный порядок вычисления?

Если мой класс C ++ перегружен оператором побитового ИЛИ (|), гарантирует ли спецификация языка C ++, что аргументы, передаваемые в серию вызовов этого оператора, будут оцениваться слева направо? Или порядок оценки определяется (или не определен)?

(IIRC C ++ встроенный | оператор имеет определенный порядок реализации; но, может быть, все по-другому, когда оператор перегружен для класса?)

Ниже приведена программа, которая иллюстрирует то, что я спрашиваю: гарантированно ли эта программа распечатывает 0 1 2 3 4 (как это происходит на Mac, на котором я сейчас сижу), или это может быть распечатано на законных основаниях 4 3 2 1 0 (или какой-то другой порядок) в определенных условиях?

#include <iostream>

class mytype_t
{
public:
mytype_t(int v) : _val(v) {/* empty */}

mytype_t operator | (const mytype_t & rhs) const {return (_val | rhs._val);}

private:
int _val;
};

mytype_t func(int v)
{
std::cout << v << std::endl;
return mytype_t(v);
}

int main(int, char **)
{
mytype_t x = func(0) | func(1) | func(2) | func(3) | func(4);
return 0;
}

1

Решение

Если встроенный оператор предписывает конкретную последовательность, аргументы оцениваются в том же порядке и для перегрузки. Вот соответствующий абзац (из n4659, проект C ++ 17), выделение мое:

[Over.match.oper]

2 Если любой из операндов имеет тип, который является классом или перечислением,
может быть объявлена ​​пользовательская операторная функция, которая реализует
этот оператор или пользовательское преобразование могут быть необходимы для преобразования
операнд типа, который подходит для встроенного оператора. В
В этом случае разрешение перегрузки используется для определения, какой оператор
функция или встроенный оператор должен быть вызван для реализации
оператор. Следовательно, запись оператора сначала преобразуется в
эквивалентная запись вызова функции, как показано в таблице 12 (где @
обозначает один из операторов, охватываемых указанным подпунктом).
Однако операнды упорядочены в порядке, установленном для
встроенный оператор
(Пункт [expr]).

Так нет, перегружен operator| не будет иметь четко определенный порядок оценки, потому что встроенный не имеет.

4

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

Других решений пока нет …