在实例方法中使用 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 &
参数)并返回一个只接受一个参数的不同函数对象(const string &
)。另一个参数固定为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(和相关的 <functional>
东西)
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的主要内容,如果未能解决你的问题,请参考以下文章