It works because of two interesting things:
- two-phase name lookup which is performed to lookup dependent names.
- and Argument Dependent Lookup (ADL).
Have a look at this:
In short, do_func
is a dependent name, so in the first phase (when the file is only parsed but the function template is not instantiated) the compiler does not resolve the name do_func
, it only checks the syntax and it sees it is a valid function call. That is all. In the second phase when the function template is instantiated (and thus T
is known), the name do_func
is resolved and at this time it also uses ADL to lookup the name.
Note that ADL works only for user-defined types. It doesn't work for built-in types, which is why your second code (i.e func(1)
) doesn't work!