在实例方法中使用 find_if

Posted

技术标签:

【中文标题】在实例方法中使用 find_if【英文标题】:Using find_if within instance method 【发布时间】:2012-04-23 13:46:49 【问题描述】:

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

我有一个.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

我从here 中遵循的示例似乎表明这相对简单......那我做错了什么?

【问题讨论】:

【参考方案1】:

问题在于FindLogDirectoryPredicate 是一个实例 方法:仅指定它的名称是不够的,您必须指定哪个对象 应该调用该方法.现在这个问题的答案对我们来说是显而易见的 (this),但对编译器来说却不是。

执行此操作的经典方法是使用

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

这是怎么回事?

mem_fun“将成员函数转换为函数对象”。也就是说,它创建了一个暴露operator() 的类型的实例(究竟是什么类型未指定,但我们不在乎)(这是我们所关心的!)。该运算符期望第一个参数是指向定义成员函数的类型的实例的指针;在这里,这将是Logger 的一个实例。

bind1st 然后接受这个带有两个参数的函数对象(第一个是指向实例的指针,第二个是原始的const string &amp; 参数)并返回一个只接受一个参数的不同函数对象(const string &amp;)。另一个参数固定为bind1st的第二个参数(this)的值。

或者,如果您可以设置FindLogDirectoryPredicate static,则不再需要指定调用哪个实例,因此问题会自动消失。

【讨论】:

谢谢 Jon(以及 sehe 和 Andrey)。我接受了这个答案,因为它提供了解释和解决方案。我已将谓词指定为静态,代码现在可以编译。现在,开始测试。再次感谢...知道它必须是相对简单的东西。【参考方案2】:

制作谓词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);  );

如果你必须使用 C++98/C++03,你也可以使用 std::mem_fun(和相关的 &lt;functional&gt; 东西)

result = std::find_if(begin(), end(), 
     std::bind1st(std::mem_fun(&Logger::FindLogDirectoryPredicate), this) );

【讨论】:

我认为 mem_fun_ref 行不通。最好的办法是调用不带参数的成员函数。您需要从 tr1 或 boost 绑定。​​ @NathanMonteleone 当然,您需要绑定参数,标准库从 C++98 开始支持该参数没问题。扩大了我的样本。 Boost也不错 “使用 lambda”是什么意思?另外,不确定您所说的“C++98/C++03”指的是什么?我收集它们是该语言的版本号,但是如何确定使用的是什么(以及给定编译器可以使用什么)? 最近的编译器(gcc、clang、VC10/11)实现了支持 lambdas 的最新 C++11 规范的(一个子集)。我的回答已经显示了它们的样子。另见C++11 support 和Lambdas @sehe Neat,我没有意识到 mem_fun 可以剥离这样的论点。【参考方案3】:

使您的谓词成为静态类成员。

static bool FindLogDirectoryPredicate(const string &str);

【讨论】:

以上是关于在实例方法中使用 find_if的主要内容,如果未能解决你的问题,请参考以下文章

6. 静态方法和实例方法

为啥在 python 中使用类方法而不是实例方法

C#中静态方法和实例化方法的区别

模型类(在 MVC 中)应该使用静态方法还是实例方法?

java中静态方法和实例方法的区别

在java中,为啥类实例也能访问静态域?