Why can std::max and std::min still be used even if I didn't #include <algorithm>?

Anthony picture Anthony · Nov 11, 2013 · Viewed 20.5k times · Source
#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;              
} 

As far as I know, the min and max functions are defined in <algorithm>.

If I didn't tell the pre-processor to include <algorithm> why does the code still work?

Answer

chwarr picture chwarr · Nov 11, 2013

Most likely, something inside of iostream has directly or indirectly included some other header that defines std::min and std::max. (Perhaps algorithm itself has been included. Perhaps some internal header that is used to implement your C++ standard library.)

You should not rely on this behavior. Include algorithm if you want std::min and std::max.

If you are used to a language with a module system where modules can import other modules and not be forced to export anything from their imports (e.g., Racket's module system), this behavior can be confusing.

Recall, however, that #include is doing textual substitution. When the #include line is processed, it is removed from the .cpp file and replaced with the contents of the file it was pointing to.

Most compilers have an option to dump the output of running the preprocessor so you can track down what is including what. You said in your comment to kmort's answer that you are using Visual Studio Express. The command line to preprocess a file to a file using the Visual C++ compiler is cl /P foo.cpp. Using this output, we can find that the definition of std::max is coming from the implementation-specific header xutility. (Placing the caret inside of the text "std:max" and pressing F12 in Visual Studio is even faster. :-] )

kmort also mentioned the /showIncludes compiler switch. Using that, we can easily track down the include chain. Here's the reduced output from my run.

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