1

我有一个二维向量,我需要删除不包含足够值的块:

typedef vector<double> iniMatrix;


bool hasInsufficientEnergy() {
return true;
}
vector<double> Audio::filter(vector<iniMatrix>&blocks, double sumThres, double ZeroThres)
{
  vector<double> totalEnergy;
  vector<double> totalZeroCross;
  double totalSum = sumThres * blocks.size();
  double totalZero = ZeroThres * blocks.size();

  vector<iniMatrix> blockked;

  for(unsigned i=0; (i < blocks.size()); i++)
  {
    totalEnergy.push_back(abs(this->energy(blocks[i])));
    totalZeroCross.push_back(zerocross(blocks[i]));

    if(!totalEnergy[i] > totalSum || totalZeroCross[i] < ZeroThres)
    {
        hasInsufficientEnergy();
    }else{
        //hasInsufficientEnergy();
    }
    iniMatrix::iterator erase_after = remove_if(blocks[i].begin(), blocks[i].end(),
                                                &hasInsufficientEnergy);
 }
 }

问题是 erase_after 并出现错误消息:

In function ‘_OutputIterator std::remove_copy_if(_InputIterator, _InputIterator, 
 _OutputIterator, _Predicate) [with _InputIterator = __gnu_cxx::__normal_iterator<double*, 
std::vector<double, std::allocator<double> > >, _OutputIterator = 
__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, 
_Predicate = bool]’:
/usr/include/c++/4.2.1/bits/stl_algo.h:1302:   instantiated from ‘_ForwardIterator 
std::remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = 
__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, 
_Predicate = bool]’
Audio.cpp:105:   instantiated from here
/usr/include/c++/4.2.1/bits/stl_algo.h:1227: error: ‘__pred’ cannot be used as a function

有人对我哪里出错有任何想法吗?

4

3 回答 3

3

to 的第三个参数std::remove_if是一个谓词函数(或任何可调用的实体,就此而言),它接受一个元素,true如果需要删除,false则返回,否则返回。在您的情况下,向量向量(或“二维向量”,如您所说)的元素是向量vector<double>。这就是谓词的参数应该是:

bool HasInsufficientEnergy(const vector<double>& elem)
{
    // herein is the code that tests elem and decides
    // whether it should be removed or not
}

那么你的filter()方法不应该包含更多

void Audio::filter(vector<iniMatrix>&blocks)
{
    auto it = std::remove_if(blocks.begin(), blocks.end(), &HasInsufficientEnergy);
    blocks.erase(it, blocks.end());
}

如果您的谓词需要额外的参数,那么将其实现为一个将它们作为构造函数参数的类。你也需要重载operator(),所以你有一个可调用的函子。如果你的编译器支持 C++11,那么学习如何使用 lambda 函数,因为它们对于这个任务非常有用。

于 2012-11-13T13:21:49.003 回答
1

remove_if, 和类似的算法,期望一个函数,而不是一个值,即你应该传递一个函数指针或函子 andouble const &并返回 abool

bool hasInsufficientEnergy(double const & element) {
    // return true if it should be removed, false otherwise
}

接着

iniMatrix::iterator erase_after = remove_if(blocks[i].begin(), blocks[i].end(), 
&hasInsufficientEnergy);

将工作

于 2012-11-13T11:20:19.047 回答
1

true或者false不是函数对象。如果你想使用remove_if你必须给它一个指向函数或函数对象的指针,它以集合的成员作为参数并返回是否删除它。查看std::remove_if中的示例

AFAICS,您可以将其替换remove_if/erase为并将其if简化为:

for(auto i=blocks.begin(); i != blocks.end(); )
{
    totalEnergy.push_back(abs(this->energy(*i)));
    totalZeroCross.push_back(zerocross(*i));

    if(!totalEnergy.rbegin() > totalSum || totalZeroCross.rbegin() < ZeroThres)
    {
        i = blocks.erase(i);
    } else {
        ++i;
    }
}
于 2012-11-13T11:29:02.617 回答