Why standard containers use function templates instead of non-template Koenig operators

前端 未结 1 1880
不思量自难忘°
不思量自难忘° 2021-01-17 10:14

This question is inspired by Issue with std::reference_wrapper. Let\' say, for example, operator< for std::vector. It\'s defined as a function t

相关标签:
1条回答
  • 2021-01-17 10:54

    Consider this code (A.h):

    template <class T>
    class A {
      public:
      T m_x;
    
      friend bool operator<(const A & lhs, const A & rhs) {
        return lhs.m_x < rhs.m_x;
      }
    };
    

    And main.cpp:

    #include "A.h"
    
    namespace buddy {
    bool operator<(const A<double> & lhs, const A<double> &rhs) {
        return lhs.m_x > rhs.m_x;
    };
    }
    using namespace buddy;
    int main(int argc, char ** argv) {
    
      A<double> a1;
      A<double> a2;
    
      a1 < a2;
    
      return 0;
    }
    

    This code does not compile:

    main.cpp:14:5: error: ambiguous overload for ‘operator<’ (operand types are ‘A’ and ‘A’) a1 < a2;

    The reason of course is that both of the operator<'s are exact matches. On the other hand, if we change the first operator< to (defined outside the class):

    template <class T>
    bool operator<(const A<T> & lhs, const A<T> & rhs) {
      return lhs.m_x < rhs.m_x;
    }
    

    The compiler stops complaining: it's now a competition between an exact match, and a function template, so the exact match is used.

    If operator< was defined in the fashion that you're suggesting, there would be no reasonable way for users of std::vector to redefine the behavior of operator<, short of specializing std::vector themselves, which is a lot more work.

    In conclusion, the standard writers elected to make it easier to overload operator<, than to provide an operator< that might be more useful in certain situations. I think they made the right choice.

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