Template func and non template func call order

后端 未结 2 765
予麋鹿
予麋鹿 2021-01-15 03:02

In Linux I get

template max() is called

But under Windows I get

non-template max() is called

Why? In Li

相关标签:
2条回答
  • 2021-01-15 03:35

    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.

    0 讨论(0)
  • 2021-01-15 03:50

    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.

    0 讨论(0)
提交回复
热议问题