【问题标题】:How to use std::bind with compose2?如何将 std::bind 与 compose2 一起使用?
【发布时间】:2015-11-04 17:20:02
【问题描述】:

我想在 C++11 中的 compose2 中使用 binary_functionstd::bind,而不使用 boost 库。

编辑: 或 labmdas。

假设我有以下定义:

bool GreaterThanFive(int x) { return x > 5; }

struct DivisibleByN : binary_function<int, int, bool> {
  bool operator()(int x, int n) const { return x % n == 0; }
};

假设我想计算大于 5 且可被 3 整除的向量的元素。我可以轻松地将它们与以下内容组合:

int NumBothCriteria(std::vector<int> v) {
  return std::count_if(v.begin(), v.end(),
                       __gnu_cxx::compose2(std::logical_and<bool>(),
                                           std::bind2nd(DivisibleByN(), 3),
                                           std::ref(GreaterThanFive)));
}

由于 bind2nd 自 C++11 起已弃用,我想移至 std::bind。我还没有弄清楚为什么以下内容不等效(并且无法编译)。

int NumBothCriteria(std::vector<int> v) {
  using namespace std::placeholders;
  return std::count_if(v.begin(), v.end(),
                       __gnu_cxx::compose2(std::logical_and<bool>(),
                                           std::bind(DivisibleByN(), _1, 3),
                                           std::ref(GreaterThanFive)));
}

它给了我以下编译错误:

no type named 'argument_type' in 'std::_Bind<DivisibleByN *(std::_Placeholder<1>, int)>`
  operator()(const typename _Operation2::argument_type& __x) const
                   ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~

我的直觉是 std::bind 没有做 std::bind2nd 所做的事情,但我不确定如何找回 argument_type 类型定义。

My search came up with three questions.第一个使用bind2nd,第二个使用boost,第三个用于C++03。不幸的是Effective STL仍然使用std::bind2nd

【问题讨论】:

  • std::bind 本身不支持合成,所以如果您将__gnu_cxx::compose2 替换为std::bind,这应该可以工作?
  • @PiotrSkotnicki 是的,你可以。不知道为什么我最初回复你说你不能。

标签: c++ c++11 stl std


【解决方案1】:

不要使用bindcompose2。以后你会感谢自己的:

int NumBothCriteria(std::vector<int> v) {
  return std::count_if(v.begin(), v.end(),
                       [](int i){ return i > 5 && i%3 == 0; });
}

您正在寻找的答案是您可以简单地使用std::bind 代替您使用__gnu_cxx::compose2 的位置:

return std::count_if(v.begin(), v.end(),
    std::bind(std::logical_and<bool>(),
        std::bind(DivisibleByN(), _1, 3),
        std::bind(GreaterThanFive, _1)));

但这比仅使用 lambda 复杂得多,也更难推理。

【讨论】:

  • 我上面的例子远比我实际做的简单。
  • @WillBeason 好吧,我敢肯定,您实际上正在做的事情也会从使用 lambda 中受益。
  • 我了解如何使用 lambdas 做到这一点。这个问题的重点是学习如何在这样的场景中使用std::bind
  • @WillBeason 答案是在这种情况下不要使用std::bind
  • 很好,我没有意识到它们可以这样嵌套!
【解决方案2】:

我想出了如何使它与std::function 一起工作。

int NumBothCriteria2(std::vector<int> v) {
  using std::placeholders::_1;
  return std::count_if(v.begin(), v.end(),
                       __gnu_cxx::compose2(std::logical_and<bool>(),
                                           std::function<int(int)>(std::bind(
                                               DivisibleByN(), _1, 3)),
                                           std::ref(GreaterThanFive)));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-03
    • 2012-10-28
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 2016-10-04
    • 2018-04-14
    相关资源
    最近更新 更多