Как происходит цепочка операторов в С++?

У меня есть основной вопрос на С++.

#include <iostream>
using namespace std;

int main() {
    int a = 255;
    cout << hex << a << endl; // <-----
}

В приведенном выше коде, как заключен оператор std::cout?

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

(((cout << hex) << a) << endl)

то есть. эквивалентно их, чтобы

  • cout << hex
  • cout << a
  • cout << endl

Но это не может быть так, потому что некоторая ценность a должна быть преобразована в форму hex!

Как операторы фактически привязаны компилятором, чтобы сделать преобразование?

Ответы

Ответ 1

Вот как обычно реализуется hex:

inline ios_base&
hex(ios_base& __base)
{
    __base.setf(ios_base::hex, ios_base::basefield);
    return __base;
}

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

EDIT (в ответ на комментарий)

Как правильно отмечает хаммар, другая часть головоломки - это то, как вызывается hex(ios_base& __base). Существует перегрузка оператора << с этой сигнатурой:

ostream& operator <<(ostream& (*)(ostream&))

Эта перегрузка является важной деталью реализации манипуляторов потока. Именно эта перегрузка вызывает hex и позволяет ей делать свою "магию" (что, конечно же, больше не должно звучать как волшебство).

Ответ 2

У вас все в порядке, это точно, как это работает. hex имеет специальный тип, который изменяет внутреннее состояние объекта cout при передаче его функции operator<<. Затем внутреннее состояние определяет, как обрабатываются любые будущие значения, прошедшие через cout через operator<<.

std::hex оказывается функцией. cout << hex не вызывает функцию hex как таковой, однако: она передает указатель на шестнадцатеричную функцию на перегрузку operator<< для ostream, которая принимает указатели на функции с определенной сигнатурой. hex() затем вызывается изнутри реализации оператора через этот указатель функции и изменяет объект ostream оттуда, насколько я знаю.

Ответ 3

std::hex фактически устанавливает флаг внутри объекта std::cout, который будет придерживаться до reset IIRC. Сами operator<< оцениваются слева направо, поэтому ваши парнеры правильны.

Ответ 4

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