我想我在设定的术语上遗漏了一些东西。
以下代码适用于对矢量进行排序:
using boost::bind;
std::vector<SegPoly> result;
//...
std::sort(result.begin(),result.end(),bind(std::less<double>(),bind(&SegPoly::getLength,_1), bind(&SegPoly::getLength,_2)));
但我不能对std::set
using boost::bind;
std::set<SegPoly> polySet(inPolys.begin(),inPolys.end(),bind(std::less<double>(),bind(&SegPoly::getLength,_1), bind(&SegPoly::getLength,_2)));
这会产生超出我能力范围的神秘编译错误:
没有用于调用'std :: set,std :: allocator&gt; :: set(__ gnu_cxx :: __ normal_iterator&gt;&gt;,__ gn_cxx :: __ normal_iterator&gt;&gt;,boost :: _ bi :: bind_t的匹配函数,boost :: _ bi :: list2,boost :: _ bi :: list1&gt;&gt;,boost :: _ bi :: bind_t,boost :: _ bi :: list1&gt;&gt;&gt;&gt;)'
任何人都知道这个错误在哪里?
答案 0 :(得分:2)
没有错误。您需要在创建std::set
时指定比较函数/仿函数,它是类型的一部分。现在,boost::bind
的类型未指定,因为根据参数,它可以创建多种类型。
解决方案可能是使用boost::function
:
typedef std::set<SegPoly, boost::function<bool(unsigned, unsigned)> > set_type;
set_type s(inPolys.begin(), inPolys.end(),
boost::bind(std::less<double>(),boost::bind(&SegPoly::getLength,_1), boost::bind(&SegPoly::getLength,_2)));
更好,更有效的选择是创建自己的比较器:
struct SegPolyComp{
bool operator()(SegPoly const& lhs, SegPoly const& rhs) const{
return lhs.getLength() < rhs.getLength();
}
}
std::set<SegPoly, SegPolyComp> s(inSegPoly.begin(), inSegPoly.end());
答案 1 :(得分:2)
如前所述(现在多次),您需要将比较器对象的类型作为模板参数传递,然后将该类型的实例作为参数传递。试图用Boost绑定做这件事......丑陋,IMO。如果你有C ++ 11可用,你可能会考虑使用lambda:
auto pred = [](SegPoly const &left, SegPoly const &right) {
return left.getLength() < right.getLength();
};
std::set<SegPoly, decltype(pred)>
polySet(inPolys.begin(),inPolys.end(), pred);
答案 2 :(得分:1)
bind返回一个函数,这是你需要进行严格弱排序所需的静态类型。
typedef std::set<foo, boost::function<bool(const foo &, const foo &)> > foos_t;
然后您可以使用bind在运行时设置该功能。这是一个完整的例子。
TEST(strict_weak) {
struct foo {
int a;
int b;
static bool with_a(const foo &lhs, const foo &rhs) {
return lhs.a < rhs.a;
}
static bool with_b(const foo &lhs, const foo &rhs) {
return lhs.b < rhs.b;
}
};
typedef std::set<foo, boost::function<bool(const foo &, const foo &)> > foos_t;
{{ // scope
foos_t foos(boost::bind(foo::with_a, _1, _2));
foo p; p.a = 4; p.b = 1;
foo q; q.a = 2; q.b = 5;
foos.insert(p);
foos.insert(q);
for (const foo &e : foos)
cout << "with_a " << e.a << ", " << e.b << endl;
}}
{{ // scope
foos_t foos(boost::bind(foo::with_b, _1, _2));
foo p; p.a = 4; p.b = 1;
foo q; q.a = 2; q.b = 5;
foos.insert(p);
foos.insert(q);
for (const foo &e : foos)
cout << "with_b " << e.a << ", " << e.b << endl;
}}
}
输出:
with_a 2, 5
with_a 4, 1
with_b 4, 1
with_b 2, 5
答案 3 :(得分:0)
比较器是集合类型的一部分。你不能只传递任何东西作为第二个参数。如果要传递bind的结果,您可能希望将比较器设为function<bool (T,T)>
,然后在构造期间传递活页夹。
我从未真正做过,所以我不能告诉你更多。祝你好运:)
从错误消息开始,它告诉你在你的集合中,没有构造函数将bind
的结果作为比较器参数。
答案 4 :(得分:0)
std::set
被声明为template < class Key, class Compare = less<Key>,
class Allocator = allocator<Key> > class set
。通过编写std::set<SegPoly>
,您迫使set
使用默认比较器std::less<SegPoly>
,而不是您定制的比较器。您已将整个类型的boost monstrosity作为模板参数传递给std::set
。
答案 5 :(得分:0)
std::set
不是序列容器;相反,它是一个 associative 容器。排序仅对序列容器有意义,其中元素以某种固定顺序(即添加它们的顺序)出现。
但是,您可能很高兴地知道,迭代std::set
可以保证按照您在定义集合类型时指定的顺序访问元素的递增顺序(默认为{ {1}})。您不能在集迭代中传递任何其他顺序。但是,您可以在创建集类型时提供自己的比较函子;只要知道比较通过“相等”来定义集合的含义。
答案 6 :(得分:0)
你不能像这样构造std :: set,因为你需要指定Comparator functor类型作为模板参数,除了函子本身作为构造函数arg。