TL;DR version: adding a new function declaration after template definition does not make it visible inside the template, except via ADL (if Visual Studio finds it, it has a bug)
at line 15, foo( n ) is a type-dependent expression (overload resolution of foo depends on the type of n, which is a template parameter and not known until instantiation)
at line 33, bar is instatiated and name lookup for foo runs. The lookup rules here are:
1) non-ADL lookup runs from template definition (line 15 and up)
2) ADL lookup runs from template definition (line 15 and up)
3) ADL lookup runs again, from instantiation (line 33 and up)
in your case, the argument is not a user-defined class or enum, ADL gives an empty set, and all you get is what's visible at line 15.
You could make it work if you used an enum:
1 2 3
|
enum MyType { one = 1 };
...
bar( one );
|