Reputation: 73443
There have been some questions on SO recently on ADL that have got me thinking. Basically, I am confused which header files compiler can search when performing ADL ? Is it only the ones included by the user's code or can it include the other header files in which the same namespace which is being used in the user's code ? For example. std
namespace spans across multiple header files. However, I may include only a subpart of it. Now if I define a function which is not in this subset of header files but is there in the std
namespace (in the file I have not included), would it still be a ambiguous call ? I got this doubts mostly because of the discussion on this question
Upvotes: 0
Views: 871
Reputation: 114481
The C++ standard defines which names each include file will bring in, however it doesn't tell that only those will be the names made available.
This means that, in theory, just including <vector>
may make available std::map
.
This is unfortunate because
Code that is incorrect because of missing include files can compile anyway because of unportable dependencies between include files in a specific implementation.
You can get lookup problems because of ADL if any of your names are also names in std
. This also can show up as a portability problem.
To explicitly answer your question: ADL will only refer to the include files that have been seen, however you cannot portably know which one they are, because on an implementation a standard file is allowed to include another standard file.
So ADL MAY look all possible standard headers, but you cannot count on that.
Upvotes: 1
Reputation: 791869
ADL is purely about lookup rules. As with all name lookups, only entities that have been previously declared can be found so if a header file is the only place where a certain declaration occurs and that header file hasn't been included directly or indirectly (yet) then the name introduced by that declaration won't be visible with or without ADL.
(This isn't quite true, as if the name being looked up is a dependent expression in a template definition the final lookup won't occur until a template specialization is instantiated, in which case subsequent declarations can influence the result of the lookup.)
All(!) ADL does is expand the namespaces searched when trying to match an unqualified-id in a function call expression to include namespaces 'related' to the parameters of the function call expression.
Upvotes: 1
Reputation: 40859
Here's how it works... There are 3 basic steps to compiling source into an executable:
There is zero overlap in these steps in C++. Include directives are preprocessor directives and therefore happen before compilation. Template instantiation is a part of compilation, therefore it happens after preprocessing. Compilers do not search outside of the current translation unit for anything. Thus no, ADL, a compile time event, cannot search headers that where not included.
The problem with your code linked in the comment to Buzz is that you can't know what headers are included or not by the standard headers. (Well, you can know if you go looking in them to find out, but the standard doesn't say.) Any one of your headers could, and apparently did, include <algorithm>
. Once that happens:
http://www2.roguewave.com/support/docs/leif/sourcepro/html/stdlibref/merge.html
Your version becomes ambiguous with one of the definitions in namespace std
because of ADL.
Upvotes: 4
Reputation: 84169
Compiler usually works on a single translation unit - that is all the source code in the input after the preprocessor made a pass over it. At that point all the headers have already been expanded recursively. The thing is that when you include a given library header file you cannot assume what other files it includes, etc. You can always check, but I'm pretty sure it's an "implementation detail".
Upvotes: 0
Reputation: 8826
No. As long as you avoid including the header that contains the definition (or including a header that includes another header that contains the definition), there would be no ambiguous call. You could define your own iostream, string, vector, etc. as long the C++ standard version has not been included (despite the fact you may have included other parts of the std namespace).
Upvotes: 1