The usual pattern for standard library function objects is to have a templated struct with a non-template operator()
. For example, std::less
looks something like so:
template <typename T>
struct less
{
bool operator()(const T& lhs, const T& rhs) const {
return lhs < rhs;
}
};
std::vector<float> vec = ...;
std::sort(vec.begin(), vec.end(), less<float>{});
My question is, why is this better than a non-template struct with a templated operator()
? It seems that the above functor would be equivalent in operation to:
struct less2
{
template <typename T>
bool operator()(const T& lhs, const T& rhs) const {
return lhs < rhs;
}
};
std::vector<float> vec = ...;
std::sort(vec.begin(), vec.end(), less2{});
except that we get the bonus of automatic type deduction. Even better, if we wanted to, we could compare different types, provided it made sense to do so:
struct less
{
template <typename T, typename U>
bool operator()(const T& lhs, const U& rhs) const {
return lhs < rhs; // compile error if operator<(T, U) is not defined
}
};
and from there it's obvious how we could use decltype
to get a truly generic std::plus
, for example. But the standard library doesn't do it that way.
Of course, I'm sure that I'm not the first person that this has occurred to, and I'm sure that there's a very good reason that the standards committee decided to go with the first pattern and not the second. I'm just not sure what it is. Can any of the gurus enlighten me?