STL find_if和不区分大小写的字符串比较
stl find_if and case-insensitive string comparison
我有一个Models
的向量,如下所示:
struct Model
{
std::string mName;
// .......
};
给定一个表示模型名称的字符串,我想看看能否在向量中找到其中一个模型。
现在我有这个:
std::string assetName = "monkey";
std::vector<Model>::iterator iter = std::find_if(mModels.begin(), mModels.end(), boost::bind(&Model::mName, _1) == assetName);
但是这不会进行不区分大小写的字符串比较。所以我读了boost/algorithm/string.hpp
, boost::iequals
,这是正确的。
这是我使用它的尝试:
std::vector<Model>::iterator iter = std::find_if(mModels.begin(), mModels.end(), boost::iequals(boost::bind(&Model::mName, _1), assetName));
但是它不能编译,并且报告了几百行编译错误。我相信std::find_if期望有一个只有1个参数的第三个参数函数。
是否有一个简单的解决方案?
编辑:我忘了说我不能使用c++ 11,但我可以使用boost!
EDIT2:下面的答案似乎给了我这个编译错误,使用这个:
std::vector<Model>::iterator iter = std::find_if(mModels.begin(), mModels.end(), boost::bind(&boost::iequals<std::string, std::string>, boost::bind(&Model::mName, _1), assetName));
bind.hpp(69): error C2825: 'F': must be a class or namespace when followed by '::'
2> bindbind_template.hpp(15) : see reference to class template instantiation 'boost::_bi::result_traits<R,F>' being compiled
2> with
2> [
2> R=boost::_bi::unspecified,
2> F=bool (__cdecl *)(const std::string &,const std::string &,const std::locale &)
2> ]
2> resourcemanifest.cpp(24) : see reference to class template instantiation 'boost::_bi::bind_t<R,F,L>' being compiled
2> with
2> [
2> R=boost::_bi::unspecified,
2> F=bool (__cdecl *)(const std::string &,const std::string &,const std::locale &),
2> L=boost::_bi::list2<boost::_bi::bind_t<const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &,boost::_mfi::dm<std::string,Model>,boost::_bi::list1<boost::arg<1>>>,boost::_bi::value<std::string>>
2> ]
调用而不是绑定函数
boost::iequals(boost::bind(&Model::mName, _1), assetName)
绑定是一个转移注意力的方法:这目前不是一个函子,而是一个函数调用。
您(意外地)试图立即调用它,并使用布尔值结果作为std::find_if
的比较函数。当然,这是不正确的。
您绑定模型名称是正确的,但是您仍然需要将实际调用绑定到iequals
。
这是Boost用户邮件列表上的一个先前的示例- bind iequals
的第一个Google结果
试试这样写:
boost::bind(
&boost::iequals<std::string,std::string>,
boost::bind(&Model::mName, _1), // 1st arg to iequals
assetName, // 2nd arg to iequals
std::locale() // 3rd arg to iequals
)
注意,这里不支持模板实参推导;还要注意,我们必须显式地提供boost::iequals
的默认第三个参数,因为默认值不能提供在绑定函数时省略参数的魔力。
完整的工作测试用例:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/algorithm/string/predicate.hpp>
struct Model
{
Model(const std::string& name) : name(name) {};
std::string mName() const
{
return name;
}
private:
std::string name;
};
int main()
{
std::vector<Model> mModels;
mModels.push_back(Model("a"));
mModels.push_back(Model("b"));
mModels.push_back(Model("c"));
const std::string assetName = "B";
std::vector<Model>::iterator it = std::find_if(
mModels.begin(),
mModels.end(),
boost::bind(
&boost::iequals<std::string,std::string>,
boost::bind(&Model::mName, _1),
assetName,
std::locale()
)
);
assert(it != mModels.end());
std::cout << it->mName() << std::endl; // expected: "b"
}
那么,为什么我原来的代码可以工作呢?
在boost::bind(&Model::mName, _1) == assetName
中,操作符==
在与boost::bind
一起执行魔术时被重载;虽然看起来像是在进行直接比较,但实际上并没有在std::find_if
的参数中进行比较,而是延迟到稍后(本质上是通过执行您无法看到的隐式bind
)。
对于一个普通的函数调用,比如boost::iequals
,我们必须自己应用这个"魔法",这就是上面所说的。
- 编写宏函数来更改字符串的大小写?
- 如何执行不区分大小写的字符串比较?
- 对字符串向量进行排序,但不区分大小写
- 如何创建一个程序来标识最长的子字符串回文,而不考虑字母大小写
- 哈希字符串更改大小写
- 在字符串的 boost::unordered_set 中使用 Lambda 函数 - 不区分大小写
- 开关大小写语句中函数中的字符串输入会导致无限循环和绕过输入
- 比较字符串大小写不区分的简单方法是什么?
- 使用 std::string 返回开关大小写块中的字符串常量
- 如何使字符串中的每个字母不区分大小写
- 不区分大小写的字符串
- 是否有函数/WinAPI 可以判断一个字符串是否以不区分大小写的语言方式以另一个字符串开头?
- 使用 map<string,int> 在开关大小写语句中使用字符串
- 处理从 std::istream 中提取字符串的空字符串大小写
- C++大小写中的类型转换常量字符串
- C++,检查两个字符串的不区分大小写相等
- 在字符串向量中查找字符串,不区分大小写的c++
- 如何按大小写顺序排列字符串(而不是按字典顺序排列)
- 内置C++函数,使两个字符串的比较不区分大小写
- 使用 std::unique_copy 从向量中提取不区分大小写的唯一字符串