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

3

19
#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?

Sallysallyann answered 11/11, 2013 at 1:57 Comment(4)
because you are under namespace std? (using namespace std;)Outer
Are you sure those are the std versions of min and max? Try fully-qualifying them.Ballance
It's possible that iostream includes algorithm but you shouldn't count on that behavior.Footbridge
I have change the codes, and i was sure to type in std::min and std::max this time, the results are the same, they still work.Sallysallyann
F
25

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
Feucht answered 11/11, 2013 at 2:6 Comment(0)
C
2

What compiler are you using?

I have seen compilers before that are somewhat "forgiving" for common items that are defined in libc or libstdc++. It will pull in the references for you. In other words, you don't have to tell it to link with it, nor include the header. It just works. While I would not have expected this of min() and max(), it's not too surprising.

This can also happen by some other header including the one you should be including, but this should not be relied on. And I don't expect it to have happened in this case.

Critter answered 11/11, 2013 at 2:8 Comment(6)
Visual Studio Express 2012Sallysallyann
Well, since you've made sure it's not some macro, you can check if iostream is actually including algorithm or not via the /showIncludes command line argument to the C++ compiler. msdn.microsoft.com/en-us/library/vstudio/…Critter
I have edited the post and change the max and min to std::max and std::min. It still works.Sallysallyann
Since your are using Visual Studio, cl.exe /P foo.cpp will produce foo.i, which contains the full preprocessed text. For me, looking around line 47885, you will see the definition of std::max from the implementation-specific header xutility. Working your way backwards through the file to find which sequence of #include statements is left as an exercise for you. It is perhaps worth nothing that your 8 line .cpp file got preprocessed into about 82,000 lines.Feucht
@kmort, that's a cool feature I've never used before. I always did it the hard way. Ya learn something new everyday.Feucht
I find it hard to believe that this is ever a result of compilers 'forgivingly pulling in the references for you', instead of indirect inclusion. And the latter was identified as the culprit in this case, despite your expectation.Chloramphenicol
N
0

Just to add the above conversations, I stumbled across a similar issue recently. If you execute the min/max calls without including the algorithm header, it'll still run fine.

std::min(value1, value2)

But if you execute it over an initializer list (put all variables in between {...}) like below,

std::min({value1, value2, value3})

the compiler throws an argument mismatch error. This might most likely be because the function overriding couldn't catch template constexpr T max (initializer_list il, Compare comp) which must only be defined inside algorithm.h. As others have answered, the basic template constexpr const T& max (const T& a, const T& b) could've been included somewhere inside of iostream. But I don't think the whole algorithm header file was included because if it was, the above snippet should've worked too.

Necroscopy answered 25/1, 2021 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.