Почему std:: max и std:: min все еще используются, даже если я не #include <algorithm>?

#include <iostream>

int main()
{
   int value1 = 1, value2 = 10;
   std::cout << "Min = " << std::min(value1,value2) <<std::endl;
   std::cout << "Max = " << std::max(value1,value2)<< std::endl;              
} 

Насколько я знаю, функции min и max определены в <algorithm>.

Если я не сказал, что предварительный процессор включил <algorithm>, почему код все еще работает?

Ответы

Ответ 1

Скорее всего, что-то внутри iostream прямо или косвенно включило какой-то другой заголовок, который определяет std::min и std::max. (Возможно, был включен сам algorithm. Возможно, некоторый внутренний заголовок, который используется для реализации стандартной библиотеки С++.)

Вы не должны полагаться на это поведение. Включите algorithm, если вы хотите, чтобы std:: min и std:: max.

Если вы привыкли к языку с модульной системой, в которой модули могут импортировать другие модули и не будут вынуждены экспортировать что-либо из своего импорта (например, в систему модулей Racket), это поведение может запутать.

Напомним, однако, что #include выполняет текстовую подстановку. Когда строка #include обрабатывается, она удаляется из файла .cpp и заменяется содержимым файла, на который он указывал.

Большинство компиляторов имеют возможность выгружать вывод работы препроцессора, чтобы вы могли отслеживать, что включает в себя. Вы сказали в своем комментарии к kmort, что используете Visual Studio Express. Командная строка препроцессор файла в файл с использованием компилятора Visual С++ cl /P foo.cpp. Используя этот вывод, мы можем обнаружить, что определение std::max происходит из заголовка xutility для реализации. (Размещение курсора внутри текста "std: max" и нажатие F12 в Visual Studio еще быстрее.: -])

kmort также упомянул переключатель компилятора /showIncludes. Используя это, мы можем легко отслеживать цепочку include. Здесь приведенный результат моего прогона.

Note: including file: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\iostream
Note: including file:  C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\istream
Note: including file:   C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\ostream
Note: including file:    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\ios
Note: including file:     C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocnum
Note: including file:      C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\streambuf
Note: including file:       C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xiosbase
Note: including file:        C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xlocale
Note: including file:         C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\stdexcept
Note: including file:          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xstring
Note: including file:           C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0
Note: including file:            C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xutility

Ответ 2

Какой компилятор вы используете?

Я видел компиляторы, прежде чем они несколько "прощаю" для обычных элементов, которые определены в libc или libstdС++. Он будет тянуть ссылки для вас. Другими словами, вам не нужно указывать ему ссылку на него и не включать заголовок. Это просто работает. Хотя я бы не ожидал этого от min() и max(), это не удивительно.

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