Search code examples
c++templatesstloperator-overloadinggeneric-programming

Why is std::less a class template?


According to 20.8.5 §1, std::less is a class template with a member function:

template<typename T>
struct less
{
    bool operator()(const T& x, const T& y) const;
    // ...
};

Which means I have to mention the type when I instantiate the template, for example std::less<int>. Why isn't std::less a normal class with a member function template instead?

struct less
{
    template<typename T, typename U>
    bool operator()(const T& x, const U& y) const;
    // ...
};

Then I could simply pass std::less to an algorithm without the type argument, which can get hairy.

Is this just for historic reasons, because early compilers (supposedly) did not support member function templates very well (or maybe even at all), or is there something more profound to it?


Solution

  • It's so that the class created by the instantiated template has nested typedefs which provide type information about the result type and argument types of the functor:

      template <class Arg1, class Arg2, class Result>
      struct binary_function 
      {
        typedef Arg1 first_argument_type;
        typedef Arg2 second_argument_type;
        typedef Result result_type;
      };
    
      template <class T> 
      struct less : binary_function <T,T,bool> 
      {
        bool operator() (const T& x, const T& y) const;
      };
    

    std::less inherits from std::binary_function, which produces these typedefs. So for example, you can extract the result type using std::less<T>::result_type.

    Nowadays, this is mostly unnecessary with C++11's decltype and auto keywords.