1

2Dベクトルがあり、十分な値を含まないブロックを削除する必要があります。

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

の3番目の引数は、単一の要素を受け取り、削除する必要がある場合と削除する必要がない場合にstd::remove_if返す述語関数(または、さらに言えば、呼び出し可能なエンティティ)です。あなたの場合、ベクトルのベクトル(またはあなたがそれを呼ぶように「2Dベクトル」)の要素はベクトルです。それがあなたの述語への議論がどうあるべきかです:truefalsevector<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をサポートしている場合は、ラムダ関数の使用方法を学習してください。ラムダ関数はまさにこのタスクに非常に役立ちます。

于 2012-11-13T13:21:49.003 に答える
1

remove_if、および同様のアルゴリズムは、値ではなく関数を期待します。つまり、関数ポインタまたは関数を渡す必要がdouble const &あります。bool

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/eraseif簡略化できます。

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 に答える