3

我有一个填充字符串向量的实例方法。我试图找到一个包含特定子字符串的向量条目(目前,该子字符串是固定的 - 简单)。

我有一个.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然后接受这个带有两个参数的函数对象(第一个是指向实例的指针,第二个是原始const string &参数)并返回一个只接受一个参数的不同函数对象(the const string &)。另一个参数固定为bind1st的第二个参数 ( this) 的值。

或者,如果您可以制作,FindLogDirectoryPredicate static则不再需要指定要在哪个实例上调用它,因此问题将自动消失。

于 2012-04-23T13:53:26.390 回答
3

做谓词static

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

或者,也许,使用 lambda。

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 回答