【问题标题】:why is std::less a functor?为什么 std::less 是函子?
【发布时间】:2013-09-13 02:08:56
【问题描述】:

为什么 less 是一个仿函数,而不是像下面的 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;
}

【问题讨论】:

  • 部分专业想和你谈谈(例如T*)。
  • 您可以通过不同的方式提供该专业化。标准可以只要求行为,实现将使用接口并使用标签调度或任何类似方法调度到实现函数(SFINAE 是新的金锤也可以在那里使用)
  • @PiotrNycz:并不是真正的复制品。虽然他们有共同的担忧,但 std::less 的一些细节使问题更加具体

标签: c++ templates


【解决方案1】:

这有不同的原因。第一个是编译器在仿函数上内联对operator() 的调用比通过函数指针内联调用更容易(当执行调用的代码本身没有内联时)。

除了性能优势之外,std::less&lt;&gt; 函子的不同用途还有更大的设计考虑因素。特别考虑任何排序的容器,例如std::set&lt;T,Comparator&gt;。您不能将指针直接作为类型传递给函数,因此为了能够使用您的myless,集合的定义必须是std::set&lt;T,bool (*)(T,T)&gt;,现在这里的下一个问题是指针没有明智的 default 构造函数会做你想做的事,所以用户代码必须在容器的构造上提供函数指针,这是一个潜在的错误。

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

忘记传递函数指针 (std::set&lt;int,bool(*)(int,int)&gt; s;) 很简单,这会给你错误的指针并导致未定义的行为。在仿函数的情况下,这不是问题,编译器将默认构造比较器成员,这将是一个有效的对象。

【讨论】:

    猜你喜欢
    • 2012-12-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    相关资源
    最近更新 更多