如何创建std :: set结构

时间:2017-01-14 09:25:26

标签: c++ stl set

我需要创建stl :: set结构。我写了

stl::set <Point> mySet; //Point - name of structure

但后来我尝试将一个结构实例添加到mySet

Point myPoint;
mySet.insert(myPoint);

有几个编译错误(错误C2784,错误C2676)。 有人可以提出建议吗?

  

1&gt; C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ include \ xfunctional(125):错误C2784:bool std :: operator&lt;(const std :: vector&lt; _Ty,_Ax&gt;&amp; ;,const std :: vector&lt; _Ty,_Ax&gt;&amp;):未能将参数带到模板&#34; const std :: vector&lt; _Ty,_Ax&gt; &安培;&#34;来自&#34; const Point&#34;

     

1&gt; C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ include \ xfunctional(125):错误C2676:二进制&#34;&lt;&#34;:&#34; const Point& #34;没有定义此运算符或转换为集成运算符可接受的类型

2 个答案:

答案 0 :(得分:8)

std::set模板提供了一个关联容器,其中包含一组有序的唯一对象。关键词有排序唯一。为了支持排序,随之而来的是一些可能性,但最终所有这些都必须导致符合strict weak ordering

std::set的第二个模板参数是比较类型。默认值std::less<Key>由标准库提供,其中Key是您在容器中存储的对象类型(在您的情况下为Point)。该默认值只是使用支持密钥类型的任何允许的可用operator <生成比较。这意味着,如果您使用默认比较器(在您的情况下为std::less<Point>),那么您的类必须假设这样的操作:

Point pt1(args);
Point pt2(args);

if (pt1 < pt2)  // <<=== this operation
    dosomething();

执行此操作的多种方法如下所示:

提供会员operator <

到目前为止,最简单的方法是为operator <课程提供成员Point。这样做pt1 < pt2变得有效,std::less<Point>就会感到高兴。假设你的类是传统的x,y点,它看起来像这样:

struct Point
{
    int x,y;

    // compare for order.     
    bool operator <(const Point& pt) const
    {
        return (x < pt.x) || ((!(pt.x < x)) && (y < pt.y));
    }
};

提供自定义比较器类型

另一种方法是提供自定义比较器类型而不是依赖std::less<Point>。这方面的最大优点是能够定义几个可能意味着不同的东西,并在容器或算法中使用它们。

struct CmpPoint
{
    bool operator()(const Point& lhs, const Point& rhs) const
    {
        return (lhs.x < rhs.x) || ((!(rhs.x < lhs.x)) && (lhs.y < rhs.y));
    }
};

有了这个,您现在可以像这样声明std::set

std::set<Point,CmpPoint> mySet;

使用此方法需要考虑的事项:该类型不是Point的一部分,因此任何对私有成员变量或函数的访问都必须通过其中的友情来计算。

提供免费功能operator <

另一种不太常见的机制是提供一个提供operator <的全局自由函数。这不是会员功能。在执行此操作时,默认std::less<Point>将导致有效代码。

bool operator <(const Point& lhs, const Point& rhs)
{
    return (lhs.x < rhs.x) || ((!(rhs.x < lhs.x)) && (lhs.y < rhs.y));
}

这似乎是自定义比较器和成员操作员的混合,实际上每个的优点和缺点都有。例如:与会员operator <一样,您可以使用默认的std::less<Point>。与自定义比较器一样,这是一个非类功能,因此必须通过友情或访问者访问私人会员。

<强>摘要

为了您的需要,我采用简单的方法;只需成为会员operator <。您可能总是希望以这种方式订购Point。如果没有,请使用自定义比较器。在 案例中,确定即表示您遵守严格的弱排序。

答案 1 :(得分:2)

要在WhozCraig's answer上进行扩展,由于C++11,您还可以使用lambda expression而不是定义比较对象。对于以下代码中的lambda表达式,我还假设您的Point类仅由xy成员组成:

auto comp = [](const Point& p1, const Point& p2) {
    return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
};
std::set<Point, decltype(comp)> mySet(comp);

Point myPoint;
mySet.insert(myPoint);

对于WhozCraig提供的解决方案,comp也必须满足strict weak ordering条件。

Code on Ideone