标准算法比较器接受不同类型的对象是否合法?

时间:2014-03-17 17:56:29

标签: c++ c++11

An answer recently posted on Stack Overflow显示的代码为标准算法提供了一个采用不同类型操作数的比较器:

  

2。使用带有模板化operator()的比较器。

     

不使用lambda,而是定义带有模板operator()的算器。

struct comparator
{
    template<typename T, typename U>
    bool operator()(T const& lhs, U const& rhs) const {
        return lhs.mCommonField < rhs.mCommonField;
    }
};
     

然后,它就像:

一样简单
std::sort(aStructs.begin(), aStructs.end(), comparator{});
std::sort(bStructs.begin(), bStructs.end(), comparator{});
// ...
std::set_intersection(aStructs.begin(), aStructs.end(),
                      bStructs.begin(), bStructs.end(),
                      std::back_inserter(intersection),
                      comparator{}
                      );
     

请注意,由于比较器中有模板,因此必须在函数范围之外声明。 Coliru Viewer上的实例。

显然,这至少可以在实践中发挥作用,工作现场演示证明了这一点。

但标准是否严格允许?

1 个答案:

答案 0 :(得分:11)

标准中的相应部分是§25.4。 Compare参数类型的唯一要求在§25.4/ 2中:

  

Compare是一个函数对象类型。当上下文转换为Compare时,应用于类型bool的对象的函数调用操作的返回值,如果调用的第一个参数小于第二个,则产生true,并且否则false。假定有序关系的算法始终使用Compare comp。假设comp不会通过解除引用的迭代器应用任何非常量函数。

换句话说,在调用时,它不能更改迭代器指向的值,并且应该对值产生严格的弱排序。由于该比较器满足这两个要求,是的,这是合法的!

事实上,这种比较函子正是N3421 - Making Operator Functors greater<>中提出的,现在是C ++ 14标准的一部分。它为标准库仿函数提供void个特性,可以完美地与相应的运算符进行前向比较(如果有的话)。例如(摘自提案文件):

namespace std
{
    template <> struct greater<void> {
      template <class T, class U> auto operator()(T&& t, U&& u) const
        -> decltype(std::forward<T>(t) > std::forward<U>(u))
           { return std::forward<T>(t) > std::forward<U>(u); }
    };
}