我有函数检查一个字符串是否只包含字母数字和下划线字符......
inline bool IsValidChar(char x)
{
return (isalnum(x) || (x == '_'));
}
我的find_if代码是:
if(find_if(str.begin(), str.end(), IsValidChar) != str.end())
{
...
}
我只想删除IsValidChar函数并直接将其内容放在find_if代码行中。
答案 0 :(得分:8)
你基本上在寻找C++0x lambda expressions:
if (find_if(str.begin(), str.end(),
[](char x) { return (isalnum(x) || x == '_'); })
!= str.end()) {
// Do something.
}
答案 1 :(得分:1)
FrédéricHamidi为您提供了一个很好的例子,说明如何使用lambda表达式来实现您的字面意思。但是,问题的标题是“如何优化此find_if代码”(强调我的)。匿名函数和命名函数之间的性能差异可以忽略不计(希望为零!)。理想情况下,任一版本都可以完全内联(假设find_if
是内联的),甚至lambda表达式和命名函数之间的细微差别也无关紧要。
如果(这是一个很大的问题)你已经分析了你的代码并发现这个表达式是性能瓶颈的根源,那么你会想要探索另一种算法来获得相同的结果。由于这是一个如此简单的测试(并且不太可能进一步简化),因此您需要了解如何在更高级别上更频繁地进行此测试。
答案 2 :(得分:1)
标准C ++
标准C ++方法从<functional>
标头开始,但它不提供所需的一切。我们必须or
两个谓词条件,虽然SGI的STL(以及因此GCC)和其他人提供它作为一个名为“compose2”的扩展,如果你的编译器缺少这样的函数,那么你可以复制实现(并阅读它在)http://accu.org/index.php/journals/443。
使用compose2,您可以写:
#include <functional>
#include <ext/functional> // where GNU g++ hides its compose2
find_if(str.begin(), str.end(),
__gnu_cxx::compose2(
std::logical_or<bool>(),
std::ptr_fun(isalnum),
std::bind1st(std::equal_to<int>(), '_')));
这一切都非常符合逻辑,但是冗长而且阅读速度慢。
使用BOOST库
领先的非标准C ++“工具箱”库 - BOOST - 提供了多种替代方案。我将说明Lambda - 请参阅http://www.boost.org/doc/libs/1_44_0/doc/html/lambda.html。
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
...
find_if(str.begin(), str.end(),
bind(isalnum, boost::lambda::_1) || boost::lambda::_1 == '_');
如果您愿意:
...
using namespace boost::lambda;
...
bind(isalnum, _1) || _1 == '_');
<强>的C ++ 0x 强>
FWIW,下一个C ++标准(现在很快就会发布,并且已经在几个流行编译器的最新版本中部分实现)将为lambda提供更好的内置支持:
...
[](char x) { return isalnum(x) || x == '_'; });
<强>讨论强>
考虑到这一切有多大麻烦,你一定想知道是否最好坚持你的开始。大概。尽管如此,如果你有很多想要使用它们的地方并且每个地方的谓词都不同,这些lambda事情确实会有所帮助。
答案 3 :(得分:0)
你可以这样做:
if(str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_")!=std::string::npos)
{
...
}
在这种情况下,我真的不认为这更清楚。 (如果你有更小或更多的任意字符集,这种方法是最干净的。)但它摆脱了额外的功能。而且,如果它很重要,它与之前的C ++标准兼容。
答案 4 :(得分:0)
我看到的主要问题是它找到了第一个有效字符。
如果要排除字符串中的无效数据,似乎需要反转谓词的意义。
inline bool IsNotValidChar(char x)
{
return (!isalnum(x) && (x != '_'));
}
if(find_if(str.begin(), str.end(), IsNotValidChar) != str.end())
{
...
}
正如其他人所说,lambda表示法使这更简洁,但不一定更清晰,绝对不会更快。