3

文字列のベクトルを設定するインスタンス メソッドがあります。特定の部分文字列を含む 1 つのベクトル エントリを見つけようとしています (今のところ、その部分文字列は固定されています - シンプルです)。

私は持ってい.hます:

namespace Data
{
namespace Shared
{

    class Logger
    {
      public:
        bool FindLogDirectoryPredicate(const string &str);
        int GetLogDirectory(string logConfigFile, string& logDirectory);
...
    }
}
}

.cpp:

#include <algorithm>
#include <vector>
#include "Logger.h"

bool Logger::FindLogDirectoryPredicate(const string &str) 
{
    // Return false if string found.
    return str.find("File=") > 0 ? false : true;
}

int Logger::GetLogDirectory(string logConfigFile, string& logDirectory)
{
    vector<string> fileContents;
    ...
    vector<string>::iterator result = find_if(fileContents.begin(), fileContents.end(), FindLogDirectoryPredicate);
    ...
}

これを Visual Studio 2010 でコンパイルすると、次のようになります。

Error   7   error C3867: 'Data::Shared::Logger::FindLogDirectoryPredicate': function call missing argument list; use '&Data::Shared::Logger::FindLogDirectoryPredicate' to create a pointer to member   Logger.cpp  317 1   Portability

find_if 呼び出しで関数 ref の前に & をスローすると、次のようになります。

Error   7   error C2276: '&' : illegal operation on bound member function expression    Logger.cpp  317 1   Portability

述語関数をクラスの外に置こうとしましたが、うまくいかなかったようで、関数が見つからないというエラーが発生しました。クラス名で述語を修飾しようとしました...アルゴリズム(ヘッダー)で別のエラーが発生しました:

Error   1   error C2064: term does not evaluate to a function taking 1 arguments    c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm    83  1   Portability

私がここからフォローしていた例は、これが比較的単純であることを示しているようです....では、何が間違っているのでしょうか?

4

3 に答える 3

4

問題は、それFindLogDirectoryPredicateインスタンスメソッドであることです。その名前を指定するだけでは十分ではありません。何らかの方法で、そのメソッドを呼び出すオブジェクトを指定する必要があります。この質問に対する答えは、私たちには明らかですが ( this)、コンパイラにはわかりません。

これを行う古典的な方法は

find_if(fileContents.begin(), 
        fileContents.end(), 
        bind1st(mem_fun(&Logger::FindLogDirectoryPredicate), this));

何が起きてる?

mem_fun「メンバー関数を関数オブジェクトに変換します」。つまり、公開するoperator()(これは私たちが気にかけていることです!) 型のインスタンス (正確にはどの型が指定されていませんが、私たちは気にしません) を作成します。この演算子は、最初のパラメーターが、メンバー関数を定義する型のインスタンスへのポインターであることを期待しています。ここでは、それは のインスタンスになりますLogger

bind1st次に、2 つのパラメーター (1 つ目はインスタンスへのポインター、2 つ目は元のconst string &パラメーター) を取るこの関数オブジェクトを受け取り、1 つのパラメーター ( ) だけを取る別の関数オブジェクトを返しますconst string &bind1stもう一方のパラメータは、の第 2 引数 ( ) の値に固定されますthis

または、作成できる場合はFindLogDirectoryPredicate static、呼び出すインスタンスを指定する必要がなくなるため、問題は自動的に解消されます。

于 2012-04-23T13:53:26.390 に答える
3

述語を作るstatic

class Logger
{
  public:
    static bool FindLogDirectoryPredicate(const string &str);
}

または、ラムダを使用してください。

result = std::find_if(begin(), end(), [&this] (const std::string& s) 
     { return FindLogDirectoryPredicate(s); } );

<functional>C++98/C++03 を使用する必要がある場合は、std::mem_fun (および関連するもの) を使用することもできます。

result = std::find_if(begin(), end(), 
     std::bind1st(std::mem_fun(&Logger::FindLogDirectoryPredicate), this) );
于 2012-04-23T13:50:32.393 に答える
-1

述語を静的クラス メンバーにします。

static bool FindLogDirectoryPredicate(const string &str);
于 2012-04-23T13:54:23.173 に答える