В c++ есть бинарный оператор <<, который для целых чисел является оператором сдвига битов числа влево на заданное количество позиций (то же, что и повторное умножение на два). Например, программа напечатает 2 << 1 == 4,
#include <iostream>
using namespace std;
int main() {
cout << "2 << 1 == " << (0b010 << 1); // 0b100
return 0;
}
Одна из основных возможностей языка - перегрузка функций, в частности встроенных операторов (не всех). То есть мы можем определить свой тип данных со своей реализацией оператора <<.
#include <iostream>
using namespace std;
struct Foo {
Foo& operator<<(int x) {
cout << "Integer: " << x << '\n';
return *this;
}
Foo& operator<<(const char* str) {
cout << "String: " << str << '\n';
return *this;
}
};
int main() {
Foo foo;
foo << 3; // Integer: 3
foo.operator<<("Hello world"); // String: Hello world
return 0;
}
Для компилятора запись foo << 3; значит именно вызов функции foo.operator<<(3). Аналогично в случае cout, объекта типа std::ostream, который представляет поток вывода (character output).
https://en.cppreference.com/w/cpp/io/basic_ostream...