Hello and welcome to C++ Weekly.
I'm your host, Jason Turner.
I'm available for code reviews, contracting,
and on site training.
Now, in this episode, I am going to discuss a very old feature
of C++ that you're possibly not aware of that's doing magic
behind the scenes for you, and maybe make you a little bit
aware of it.
So let's just start very simple.
I'm going to make a vector.
And I have going to call this my vector here
of integers called vec.
Now, I'm going to call a function called
begin on this vec.
That is all I am going to do.
This is giving me the iterator to the beginning of the vector.
Now, depending on your level of experience with C++,
you might either say, I know exactly why that compiles or I
have no idea why that compiles, or perhaps, mainly,
you don't even know why this is even a question why this should
compile.
Now, what it comes down to is the fact
that this function, begin, does not
exist in the global namespace.
Everything in the C++ standard library is in a namespace,
generally, the STD namespace.
So somewhere in the STD namespace,
there's a function called begin, and we're
able to call it magically without having
to put this right here.
These two things are effectively equivalent.
Now, generally speaking, it is undefined behavior
to add something to the STD namespace yourself.
So this is just for illustrative purposes.
But how is it possible that I'm able to call the function
like this or like this?
So let's go ahead and make our own types,
and see what happens.
And really, none of this matters as far as what these things do
or what they look like.
So I'm going to go ahead and create an object of type s,
and then I am going to use it.
And again, you might care or not care why
does this even compile at all.
So this feature, called argument dependent look up, or ADL,
looks in the surrounding namespace
for the types of parameters that are
being utilized in this thing.
So there's all kinds of handiness for this.
This is one reason why we are able to do things like--
because this operator insertion overload,
right here, exists in the STD namespace,
and somehow it manages to find it for us.
That's one reason why ADL exists,
and one way that it's helpful.
But it, perhaps, can surprise you in some ways
in calling functions that you maybe wouldn't otherwise
expect it to be able to call, and we
might be able to play with that a bit as well.
Now, this is confusingly named, but if you are using libraries
that have similar types--
similar names across them--
and are properly in two different name spaces,
you might not really appreciate that
by doing that, this is now calling a different function.
And you might also wonder, well, how hard will it
search to find things from different namespaces?
So let's try this.
I'm saying, explicitly, that this function works with one
from a different namespace.
And now, I'm getting this invalid initialization
of reference of type void from an expression of type--
so this is NS to NS2.
And we might have been left with the question
of is this ambiguous?
Or how is it going to attempt to find this?
So if some automatic conversion existed,
which would truly be a worst case scenario here,
then it might be able to call a different function than we
expected it to.
So it is possible that at some point in your code,
you might be utilizing ADL without realizing it,
and you may find some unexpected behavior from the compiler.
And I would say, generally, these
are things that would be caught at compile time,
and it's not going to cause you some runtime issue,
but it is, perhaps, a very rare case,
where you're not calling the function that you
thought you were calling.
But again, this feature does exist for real reasons,
and I know that there are people considering alternatives to it.
So thanks for watching this episode of C++ Weekly.
I hope you learned a little bit about ADL and maybe something
about C++ that you did not know previously.