std :: list remove_if使用堆栈中的状态

时间:2014-07-15 14:31:02

标签: c++ list closures

我想从std::list中删除具有线性复杂度的元素(仅通过列表中的每个元素一次)。我需要这样做,具体取决于堆栈中变量的值:

int somevalue= 5;
int count=0;
mylist.remove_if( 
    [](MyStructure* s)
    { 
        if (s->somefield==somevalue) 
        {
            count++;
            return true;
        }
        else
        return false;
    });

当然,这不起作用 - somevalue是堆栈中的变量。

我尝试过使用模板函数,只是为了实现(在illegal operation on bound member function expression之后)你无法在这种情况下真正使用它们。我知道我需要以某种方式制作一个闭包,所以我读过this question,但我还不能使用C++0x而我无法使用其他答案来适应我的用例,因为我没有真的明白operator是否有一些魔力。

或者,有没有办法在给定迭代器的当前位置的情况下从列表中删除元素(不再遍历整个列表来查找元素)?

4 个答案:

答案 0 :(得分:1)

就lambda表达式(c ++ 11特性)而言,您可以按以下方式捕获somevalue[somevalue](...) {...}

答案 1 :(得分:1)

您必须在lambda表达式中捕获somevalue才能使用它:

示例(实时here):

struct MyStructure
{
    int somefield;
};

int main(int argc, char** argv) {

  std::list<MyStructure> my_list = { { 1 }, { 2 }, { 1 }, { 3 }, { 2 }, { 1 } };
  int somevalue = 2;
  my_list.remove_if( [somevalue](MyStructure s){ return s.somefield == somevalue; });
  //                   ^^^^^^
  //                   Capture      

  for(auto& s : my_list)
      std::cout << s.somefield << " ";
  return 0;
}

答案 2 :(得分:1)

您需要捕获示例代码中的变量:

int somevalue= 5;
mylist.remove_if( [somevalue](MyStructure* s){ s->somefield==somevalue });

如果没有使用C ++ 11,你需要自己制作仿函数:

// For static constant check
template <int CheckValue>
struct Equal {
    operator()(const MyStructure* s) { return s->somefield == CheckValue; }
};

mylist.remove_if(Equal<5>);

..or..

// For dynamic constant check as the sample code
struct Equal {
    Equal(int check_value) : m_check_value(check_value) {}
    operator()(const MyStructure* s) { return s->somefield == m_check_value; }
private:
    int m_check_value;
};

mylist.remove_if(Equal(somevalue));

答案 3 :(得分:-1)

迭代元素以确定要删除的元素。使用erase删除已标识的元素,并继续从返回的迭代器进行迭代。

类似的东西:

int somevalue=5;
std::list<MyStructure*> myList;
// ...
std::list<MyStructure*>::iterator it=myList.begin();
while(it!=myList.end())
{
  if ((*it)->somefield==somevalue)
  {
    it = myList.erase(it);
  }
  else
  {
    ++it;
  }
}