1

Why is less a functor rather then a templated function like myless below? Why did the committee decide on that and where can I go for further reading? Also does the C++11 standard explain why the committee made certain decisions?

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

#if 1

template <class T> struct stdless {
  bool operator() (const T& x, const T& y) const {return x<y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef bool result_type;
};

#else
    #define stdless std::less
#endif

//bool myless(int a, int b) { return a<b; }
template<class T>
bool myless(T a, T b) { return a<b; }

int main()
{
    vector<int> a{5, 3, 1,6};

    myless(5, 6);
    stdless<int>()(5, 6);

    auto fn1=stdless<int>();
    fn1(5,9);
    auto fn2=myless<int>;
    fn2(5,9);

    sort(a.begin(), a.end(), myless<int>);
    sort(a.begin(), a.end(), less<int>());

    for(auto b=a.begin(); b!=a.end(); ++b)
        cout << *b<<endl;
}
  • 2
    Partial specializations want a word with you (`T*`, for example). – Xeo Sep 09 '13 at 14:41
  • possible duplicate of [Why use functors over functions?](http://stackoverflow.com/questions/6451866/why-use-functors-over-functions) – PiotrNycz Sep 09 '13 at 14:49
  • You can potentially provide that *specialization* in a different way. The standard could just mandate the behavior, and the implementation would use an interface and dispatch to an implementation function using tag-dispatch or any similar approach (SFINAE being the new golden hammer could also be used there) – David Rodríguez - dribeas Sep 09 '13 at 14:52
  • 3
    @PiotrNycz: Not really a duplicate. While they share a common set of concerns, there are specifics of `std::less` that make the question a bit more specific – David Rodríguez - dribeas Sep 09 '13 at 15:02

1 Answers1

6

There are different reasons for that. The first one, is that it is easier for the compiler to inline the call to operator() on a functor than to inline a call through a pointer to function (when the code doing the call is not inlined itself).

Beyond that performance advantage, there are bigger design considerations at hand with different uses of the std::less<> functor. In particular consider any of the sorted containers, like std::set<T,Comparator>. You cannot pass a pointer to function directly as a type, so to be able to use your myless the definition of the set would have to be std::set<T,bool (*)(T,T)>, now the next problem here is that pointers don't have sensible default constructor that would do what you want, so user code must provide the function pointer on construction of the container, which is a potential for errors.

std::set<int, bool(*)(int,int)> s(&myless);

It is simple to just forget to pass the function pointer (std::set<int,bool(*)(int,int)> s;) and that will get you the wrong pointer and cause undefined behavior. In the case of a functor this is not a problem, the compiler will default construct the comparator member and that will be a valid object.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489