向量中元素范围的迭代器,其属性具有特定值

时间:2012-12-13 11:02:39

标签: c++ stl vector g++

我有一个对象向量,我想返回其属性具有特定值的元素范围。这是结构:

class A {
public:
  std::vector<B*> vec_;
  pair<vector<B*>::iterator, vector<B*>::iterator> getElements(unsigned int attr_val);
  unsigned int name() { return name_; }
private:
  unsigned int name_;
};

class B {
public:
  unsigned int attr() { return attr_; }
  A* source() { return source_; }
  B* dest() { return dest_; }
private:
  A* source_;
  B* dest_;
  unsigned int attr_;
};

向量vec_已按attr_dest_->name()排序(按此顺序)。现在我想要返回attr_等于attr_val的所有元素。

实施getElements(unsigned int attr_val)的适当的stl算法(或者甚至是矢量成员函数?)是什么?

2 个答案:

答案 0 :(得分:2)

你需要一个值传递给equal_range,显而易见的是指针。获得一个的显而易见的方法是创建一个B的实例,其值为attr_,并编写一个只涉及attr()值的比较器。我假设你已经知道如何做到这一点,因为你设法得到矢量排序; - )

如果向量中没有空指针,则可以改为:

struct FindAttr {
    unsigned int attr;
    FindAttr(unsigned int attr) : attr(attr) {}
    bool operator()(B *left, B *right) {
        unsigned int leftval = left ? left->attr() : attr;
        unsigned int rightval = right ? right->attr() : attr;
        return leftval < rightval;
    }
};

...

return equal_range(vec_.begin(), vec_.end(), nullptr, FindAttr(value));

你可以做一个lambda:

return equal_range(vec_.begin(), vec_.end(), nullptr, [=value](B *left, B *right) {
    unsigned int leftval = left ? left->attr() : attr;
    unsigned int rightval = right ? right->attr() : attr;
    return leftval < rightval;
});

你实际上可以完全删除指针,给出我认为“最干净”的解决方案:

struct FindAttr {
    bool operator()(B *left, unsigned int rightval) {
        return left->attr() < rightval;
    }
    bool operator()(unsigned int leftval, B *right) {
        return leftval < right->attr();
    }
};

...

return equal_range(vec_.begin(), vec_.end(), value, FindAttr());

AFAIK与lambda没有直接等价,因为lambdas只能有一个调用签名。我想你可以编写一个带有boost::variant的lambda(或任何从unsigned intB*隐式转换的类型,并记住它是哪一个。)

答案 1 :(得分:0)

您正在寻找std::equal_range,它基本上可以满足您的需求。界面是:

pair<It, It> equal_range(It first,
                         It last,
                         const T& value,
                         Compare comp);

comp默认为std::less,后者又调用运算符<

在您的情况下,实施可能是:

bool comparer(B* el, unsigned int value)
{
  return el->attr() < value;
}

pair<vector<B*>::iterator, vector<B*>::iterator> A::getElements(unsigned int attr_val)
{
  return equal_range(vec_.begin(), vec_end(), attr_val, comparer);
}