In Linux I get
template max() is called
But under Windows I get
non-template max() is called
Why? In Li
In pre-standard C++, you would likely get the non-template max
.
(Without a standard, it's hard to say what you should get, but all of
the pre-standard compilers I know would defer name-lookup to
instantiation.) Since C++89, you should get template max
; name lookup
occurs in two phases: when the template is defined (at which point, only
the template max
is visible), and when the template is instantiated,
but at the instantiation point, only for dependent names, and only using
ADL. In your code, max
is a dependent name, but the symbols
triggering ADL are std::vector
(which draws in std
) and int
, which
doesn't add anything, not even the global namespace. So the
non-template max
is not found.
These rules were among the last formalized by the C++ committee, and compilers can't change overnight, so practically speaking, if the compiler dates from anytime before 1995, you can probably expect the pre-standard behavior. For anything later, I'd tend to consider it a compiler error, but... compilers have to support existing code, and ideally, later compilers will have an option to use the previous name lookup rules. (I say ideally, because having two incompatible sets of name lookup rules is decidedly non-trivial. Just getting one set correct is difficult enough for most compiler implementors.)
And it's fairly well known that Microsoft's implementation of templates is not standard conformant, even today.
The call of max
in Imax
depend on T and thus max should be searched in the template definition context (where the template max is) and combined with the argument dependent lookup in the instantiation context. ADL shouldn't find the free standing max as int
have no associated namespace. So my take is that gcc is correct.
Note that if you have the slight variation:
#include <iostream>
#include <vector>
struct S {};
template < typename T >
inline void max( const S& a, const T& b )
{
std::cout << "template max() is called" << std::endl;
}
template < typename T >
inline void Imax( const S& a, const std::vector<T>& b)
{
max(a, b[0]);
}
inline void max( const S& a, const S& b )
{
std::cout << "non-template max() is called" << std::endl;
}
int main()
{
std::vector<S> v;
v.push_back(S());
Imax(S(), v);
return 0;
}
here, the global namespace is associated with S, and thus the non template max is found by the ADL lookup at the point of instantiation.