为什么不是一个仿函数而不是像下面的myless这样的模板化函数?为什么委员会决定这一点以及我可以在哪里进一步阅读?C++ 11标准也解释了为什么委员会做出了某些决定?
#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;
}
Run Code Online (Sandbox Code Playgroud)
这有不同的原因.第一个是,编译器更容易内联operator()对仿函数的调用,而不是通过指向函数的指针内联调用(当执行调用的代码本身没有内联时).
除了性能优势之外,还有更大的设计考虑因素与std::less<>functor的不同用途.特别要考虑任何已分类的容器,例如std::set<T,Comparator>.你不能直接将指针作为一个类型传递给函数,所以为了能够使用你myless的集合的定义必须是std::set<T,bool (*)(T,T)>,现在这里的下一个问题是指针没有合理的默认构造函数,可以做你想要的,因此用户代码必须在容器的构造上提供函数指针,这可能是错误.
std::set<int, bool(*)(int,int)> s(&myless);
Run Code Online (Sandbox Code Playgroud)
忘记传递函数指针(std::set<int,bool(*)(int,int)> s;)很简单,这将导致错误的指针并导致未定义的行为.在仿函数的情况下这不是问题,编译器将默认构造比较器成员并且它将是有效对象.