Ответ 1
Во-первых, компилятор будет смотреть на типы слева и справа от <<
. std::cout
имеет тип std::ostream
, строковый литерал имеет массив типов из 15 const char
. Поскольку левый тип класса, он будет искать функцию с именем operator<<
. Вопрос в том, где он будет выглядеть?
Поиск этого имени operator<<
- это так называемый неквалифицированный поиск, потому что имя функции не имеет значения, например std::operator<<
. Неквалифицированный поиск имен функций вызывает зависящий от аргумента поиск. Поиск зависимых от аргументов поиска будет искать в классах и пространствах имен, связанных с типами аргументов.
Когда вы включаете <iostream>
, свободная функция подписи
template<typename traits>
std::basic_ostream<char, traits>& operator<<(std::basic_ostream<char, traits>&,
const char*);
объявлен в пространстве имен std
. Это пространство имен связано с типом std::cout
, поэтому эта функция будет найдена.
std::ostream
- это просто typedef для std::basic_ostream<char, std::char_traits<char>>
, а массив из 15 const char
может быть неявно преобразован в char const*
(указывая на первый элемент массива). Поэтому эту функцию можно вызывать с двумя типами аргументов.
Существуют и другие перегрузки operator<<
, но указанная выше функция является наилучшим соответствием для типов аргументов и выбранного в этом случае.
Простой пример зависящего от аргумента поиска:
namespace my_namespace
{
struct X {};
void find_me(X) {}
}
int main()
{
my_namespace::X x;
find_me(x); // finds my_namespace::find_me because of the argument type
}
N.B. Поскольку эта функция является оператором, фактический поиск немного сложнее. Он просматривается с помощью квалифицированного поиска в области первого аргумента (если это тип класса), т.е. Как функция-член. Кроме того, выполняется неквалифицированный поиск, но игнорируется все функции-члены. Результат несколько отличается, потому что неквалифицированный поиск на самом деле похож на двухэтапную процедуру, где зависимым от аргумента поиска является второй шаг. Если первый шаг находит функцию-член, второй этап не выполняется, то есть поиск по запросу не используется.
Для сравнения:
namespace my_namespace
{
struct X
{
void find_me(X, int) {}
void search();
};
void find_me(X, double) {}
void X::search() {
find_me(*this, 2.5); // only finds X::find_me(int)
// pure unqualified lookup (1st step) finds the member function
// argument-dependent lookup is not performed
}
}
в
namespace my_namespace
{
struct X
{
void operator<<(int) {}
void search();
};
void operator<<(X, double) {}
void X::search() {
*this << 2.5; // find both because both steps are always performed
// and overload resolution selects the free function
}
}