Boost.Lambda:插入不同的数据结构

时间:2008-11-10 23:53:52

标签: c++ boost-lambda

我想要vector插入set。这是三个不同的调用之一(另外两个更复杂,涉及boost::lambda::if_()),但解决这个简单的情况将帮助我解决其他问题。

std::vector<std::string> s_vector;
std::set<std::string> s_set;
std::for_each(s_vector.begin(), s_vector.end(), s_set.insert(boost::lambda::_1));

很遗憾,此操作失败并显示转换错误消息(尝试将boost::lambda::placeholder1_type转换为std::string)。

那么......这有什么问题?

5 个答案:

答案 0 :(得分:3)

  

错误真的很讨厌,但可归结为它无法弄清楚使用哪个set :: insert,因为有三个重载。

你可以通过指定一个指向你想要使用的函数的指针来解决这个歧义问题:

typedef std::set<std::string> s_type;
typedef std::pair<s_type::iterator, bool>(s_type::*insert_fp)(const s_type::value_type&);
std::for_each(s_vector.begin(), s_vector.end(), boost::bind(static_cast<insert_fp>(&s_type::insert), &s_set, _1));

它不漂亮,但它应该有用。

答案 1 :(得分:2)

我会使用for循环:-D

答案 2 :(得分:2)

要将向量复制到集合中,可以使用std :: copy和插入迭代器。类似的东西:

std::copy(s_vector.begin(), s_vector.end(), std::inserter(s_set, s_set.end()));

当然这根本不使用boost :: lambda,所以它可能无法帮助你将其概括为你想做的事情。最好还要了解更多关于你在这里尝试做什么的事情。基于你提到的lambda :: _ if,我将假设你的lambda在插入集合之前会对输入向量进行某种过滤。

以下(完整的,经过测试的)示例显示了如何仅将来自向量的&lt; = 4个字符的字符串复制到集合中:

#include <boost/assign/list_of.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/test/minimal.hpp>

#include <set>
#include <vector>
#include <algorithm>

using namespace std;
using namespace boost::lambda;
using namespace boost::assign;

int test_main(int argc, char* argv[])
{
    vector<string> s_vector = list_of("red")("orange")("yellow")("blue")("indigo")("violet");
    set<string> s_set;

    // Copy only strings length<=4 into set:

    std::remove_copy_if(s_vector.begin(), s_vector.end(), std::inserter(s_set, s_set.end()),
                        bind(&string::length, _1) > 4u);

    BOOST_CHECK(s_set.size() == 2);
    BOOST_CHECK(s_set.count("red"));
    BOOST_CHECK(s_set.count("blue"));

    return 0;
}

希望这能让你继续下去吗?

另外,让我重申上面提到的观点,即boost :: bind和boost :: lambda :: bind是两种不同的野兽。从概念上讲,它们是相似的,但它们产生不同类型的输出。只有后者可以与其他lambda运算符结合使用。

答案 3 :(得分:1)

我认为问题的一部分是for_each()期待一个仿函数,并且你传递函数调用的结果。因此,您的代码首先会调用vector<string>::insert(),然后将该调用的结果传递给for_each()。我不确定确切的语法,但我认为你想在这里结合使用bind和lambda。 e.g。

for_each(s_vector.begin(), s_vector.end(),
         boost::bind(set<string>::insert, s_set, boost::lambda::_1));

答案 4 :(得分:0)

不幸的是,这个:

std::for_each(s_vector.begin(), s_vector.end(),
        lambda::bind(&std::set<std::string>::insert, s_set, lambda::_1));

不起作用。 (注意我使用了set :: insert,因为这就是s_set。)错误真的很讨厌,但归结为它无法弄清楚使用哪个set :: insert,因为有三个重载。我正在尝试使用的是将返回pair :: iterator,bool&gt;的集合。 (值插入)。显然,这不起作用。

我注意到你使用了boost :: bind,而不是boost :: lambda :: bind - 是故意的吗? (它们似乎有点不同。)

我认为你期待一个仿函数而不是函数调用结果是正确的;我确信这可以变成一个仿函数,但我的大脑现在还没有看到答案。

感谢。