std::bind 如何绑定传递给 std::sort 的两个不同类型参数的二元运算?

How can std::bind bind a binary operation of two different-type parameters passed in to std::sort?

在这个例子中,我应该根据给定的大小对字符串向量进行排序,比如长度大于或等于给定大小的元素排在第一位,然后是剩余的。

这就是我所做的:

bool is_shorter(std::string const& str, std::string::size_type sz){
    return !(str.size() < sz);
}

int main(){

    std::vector<string> vstr{"vector", "In", "this", "example", "am", "supposed",
      "sort", "a", "of", "I", "strings", "depending"};

    std::string::size_type len = 5;
//    std::sort( vstr.begin(), vstr.end(),
//        std::bind(is_shorter, placeholders::_1, len) );

    std::sort( vstr.begin(), vstr.end(),
        std::bind( [](std::string const& str, std::string::size_type sz){
            return !(str.size() < sz);}, std::placeholders::_1, len ) );

    for(auto const& str : vstr)
        std::cout << str << ", ";
    std::cout << '\n';


    std::cout << '\n';
}

输出:

depending, strings, supposed, example, vector, In, this, am, sort, a, of, I,

我的意思是比较运算是一个二元运算,它被称为每个连续元素的每次迭代。这些元素属于同一类型(属于序列中的元素)。

lambda 传入或自定义比较操作是否采用相同类型的参数对我来说无关紧要:

例如,对字符串向量进行排序,使等于给定字符串的元素首先出现:

  std::sort(vstr.begin(), vstr.end(),
        std::bind([](std::string s1, std::string s2 ){ return s1 == s2;}, _1, std::string("vector")
    ));

不完全相关,但你的答案是错误的:“depending, strings, supposed, example, vector, In, this, am, sort, a, of, I”,注意“In”在“this”之前”和“排序”。您的排序函数应该比较两个输入字符串的大小。

现在,'How does bind work?'。基本上,当您调用 std::bind 时,它 copies/moves 将所有附加参数提供到返回的数据结构中。此结构具有模板化 operator()。传递给 operator() 的参数将替换调用绑定期间提供的 std::placeholders 对象。这里的重要部分是调用期间传递的任何未提及的参数都不会转发给绑定的仿函数。

所以在这种情况下,因为您没有将 std::placeholders:_2 传递给绑定调用,所以第二个参数被丢弃。 lambda 的第二个参数由您传入的 len 填充。

std::bind 中有更多功能,但这涵盖了最简单的用例。

问题是,您实际上并不想要 sort 数组。 (你可以这样做,通过编写一个比较器,如果第一个字符串短于限制而第二个字符串长于限制,则 returned true,否则 false,但这将是低效和复杂的。)

你想要的是 std::partition,它采用 一元 谓词,并对数组重新排序,以便谓词 return true for 被移到数组的前面,谓词 returns false 的被移到数组的末尾。

一旦您使用采用一元谓词的算法,您当前的部分绑定方法就可以正常工作。