I just copy the example from "notebook"
int foo(void*); template<typename T> struct S { S() { int i = foo(0); } // A standard-compliant compiler is supposed to // resolve the 'foo(0)' call here (ie early) and // bind it to 'foo(void*)' }; void foo(int); int main() { S<int> s; // VS2005 will resolve the 'foo(0)' call here (ie // late, during instantiation of 'S::S()') and // bind it to 'foo(int)', reporting an error in the // initialization of 'i' }
The above code should compile in the standard C ++ compiler. However, MSVC (2005 as well as 2010 Express) will report an error due to improper implementation of the two-phase search.
And if you look closer, the problem is actually two-layer. At first glance, it is obvious that the Microsoft compiler does not perform an early (first stage) search for the independent expression foo(0) . But what he does after that does not really behave as the correct implementation of the second phase of the search.
The language specification clearly states that in the second stage of the search, only extended ADL namespaces are expanded with additional declarations accumulated between the definition point and the instantiation point. Meanwhile, a non-ADL search (i.e., a regular unqualified name search) is not expanded by the second phase - it still sees those and only those ads that were visible in the first stage.
This means that in the above example, the compiler should not see void foo(int) in the second phase. In other words, the behavior of MSVC cannot be described simply "MSVC postpones the entire search until the second phase." What the MSVC implements is not a proper implementation of the second phase.
To better illustrate this issue, consider the following example.
namespace N { struct S {}; } void bar(void *) {} template <typename T> void foo(T *t) { bar(t); } void bar(N::S *s) {} int main() { N::S s; foo(&s); }
Please note that even if the call to bar(t) inside the template definition is a dependent expression allowed in the second phase of the search, it should still solve void bar(void *) . In this case, ADL does not help the compiler find the void bar(N::S *s) , while the regular unskilled search should not be "expanded" by the second phase and, therefore, should not also see the void bar(N::S *s)
However, the Microsoft compiler allows the call to void bar(N::S *s) . This is not true.
The issue is still present in its original glory in VS2015.