如何使用一些 boost 库使 std::find_if 和 std::map 一起工作?

发布于 2024-12-03 07:33:10 字数 2005 浏览 1 评论 0原文

这个问题的灵感来自 另一个问题提出这个问题的主题

从地图容器中查找第一个大于用户指定值的值

这可以通过多种方式解决。典型的 C++03 解决方案定义一个专用函数(或函子)并将其作为第三个参数传递给 std::find_if 。

在 C++11 中,可以避免定义专用函数(或函子),而是可以使用 lambda as: ,

auto it = std:: find_if(m.begin(), mp.end(), 
                    [n](const std::pair<std::string, int> & x) -> bool
                       { return x.second > n; }
                   );

接受的回答

我仍在寻找一个简短而酷的解决方案。如果它是一个向量,那么我刚刚学习了一个很酷的解决方案,它利用 Boost.Phoenix 并且该解决方案变得非常简洁(ideone demo):

std::vector<int> v = ...;
auto it = std::find_if(v.begin(), v.end(), arg1 > 4);

这里 arg1 是在 boost::phoenix::arg_names 命名空间中定义的函子对象,表达式arg1>4 计算出另一个函子,然后将其传递给 std::find_if

一个快速测试是(ideone),

std::cout<< (arg1 > 9)(v) << std::endl; //prints 0 if as v > 9 is false, else 1

//or store the functor first and then use it
const auto & f = arg1 > 9;
std::cout<<  f(v) << std::endl; //prints 0 if as v > 9 is false, else 1

我的问题是,我想以类似的方式解决地图问题。有这样的解决办法吗?类似于:

auto it = std::find_if(m.begin(),mp.end(), (???).second > n); //m is std::map

或者,

auto it = std::find_if(m.begin(),mp.end(), at<1>(arg1) > n);  //m is std::map

要使其正常工作,表达式 at<1>(arg1) >; 2 必须求值为一个以 const std::pair & 作为参数的函子。我的直觉告诉我 boost 有这个解决方案。 :-)

This question is inspired from another topic which poses this question:

Find the first value greater than user specified value from a map container

which can be solved in several ways. A typical C++03 solution defines a dedicated function (or functor) and pass it to std::find_if as third argument.

In C++11, one can avoid defining a dedicated function (or functor), and can instead make use of lambda as:

auto it = std:: find_if(m.begin(), mp.end(), 
                    [n](const std::pair<std::string, int> & x) -> bool
                       { return x.second > n; }
                   );

which is the accepted answer.

I'm still looking for a short and cool solution. If it were a vector, then I just learnt a cool solution which makes use of Boost.Phoenix and the solution becomes very concise (ideone demo):

std::vector<int> v = ...;
auto it = std::find_if(v.begin(), v.end(), arg1 > 4);

Here arg1 is a functor object defined in boost::phoenix::arg_names namespace, and the expression arg1>4 evaluates to another functor which then gets passed to std::find_if.

A quick test is (ideone),

std::cout<< (arg1 > 9)(v) << std::endl; //prints 0 if as v > 9 is false, else 1

//or store the functor first and then use it
const auto & f = arg1 > 9;
std::cout<<  f(v) << std::endl; //prints 0 if as v > 9 is false, else 1

My question is, I want to solve the map problem, in a similar way. Is there any such solution? Something like:

auto it = std::find_if(m.begin(),mp.end(), (???).second > n); //m is std::map

Or,

auto it = std::find_if(m.begin(),mp.end(), at<1>(arg1) > n);  //m is std::map

For it to work, the expression at<1>(arg1) > 2 has to evaluate to a functor which takes const std::pair & as argument. My gut feelings tells me that boost has this solution. :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

终遇你 2024-12-10 07:33:10

事实上,Boost.Fusion 和 Boost.Phoenix 正是您想要的内置内容。

如果包含必要的标头来 adapt std::pair<> 作为符合 Fusion 序列,然后可以使用 Phoenix 的惰性版本 boost::fusion::at_c 来访问std::pair<>::firststd::pair<>::second (请务必#include)。

namespace phx = boost::phoenix;
using phx::arg_names::arg1;

auto it = std::find_if(m.begin(), m.end(), phx::at_c<1>(arg1) > n);

编辑:完整示例,使用 VC++ 2010 SP1 + Boost 1.47.0 进行测试:

#include <algorithm>
#include <map>
#include <string>
#include <iostream>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/fusion.hpp>

int main()
{
    namespace phx = boost::phoenix;
    using phx::arg_names::arg1;

    std::map<std::string, int> m;
    m["foo"]    = 1;
    m["bar"]    = 2;
    m["baz"]    = 3;
    m["qux"]    = 4;
    m["quux"]   = 5;
    m["corge"]  = 6;
    m["grault"] = 7;
    m["garply"] = 8;
    m["waldo"]  = 9;
    m["fred"]   = 10;
    m["plugh"]  = 11;
    m["xyzzy"]  = 12;
    m["thud"]   = 13;

    int const n = 6;
    auto it = std::find_if(m.cbegin(), m.cend(), phx::at_c<1>(arg1) > n);
    if (it != m.cend())
        std::cout << it->first << '\n'; // prints "fred"
}

Indeed, Boost.Fusion and Boost.Phoenix have exactly what you want built-in.

If one includes the necessary header to adapt std::pair<> as a conforming Fusion sequence, then one can use Phoenix's lazy version of boost::fusion::at_c<> to access std::pair<>::first or std::pair<>::second (be sure to #include <boost/phoenix/fusion.hpp>).

namespace phx = boost::phoenix;
using phx::arg_names::arg1;

auto it = std::find_if(m.begin(), m.end(), phx::at_c<1>(arg1) > n);

EDIT: Full sample, tested with VC++ 2010 SP1 + Boost 1.47.0:

#include <algorithm>
#include <map>
#include <string>
#include <iostream>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/fusion.hpp>

int main()
{
    namespace phx = boost::phoenix;
    using phx::arg_names::arg1;

    std::map<std::string, int> m;
    m["foo"]    = 1;
    m["bar"]    = 2;
    m["baz"]    = 3;
    m["qux"]    = 4;
    m["quux"]   = 5;
    m["corge"]  = 6;
    m["grault"] = 7;
    m["garply"] = 8;
    m["waldo"]  = 9;
    m["fred"]   = 10;
    m["plugh"]  = 11;
    m["xyzzy"]  = 12;
    m["thud"]   = 13;

    int const n = 6;
    auto it = std::find_if(m.cbegin(), m.cend(), phx::at_c<1>(arg1) > n);
    if (it != m.cend())
        std::cout << it->first << '\n'; // prints "fred"
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文