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

Если мой класс 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| не будет иметь четко определенный порядок оценки, потому что встроенный не имеет.

Другие вопросы по тегам