我有一个std::vector
个指针Person
个对象,它们有一个成员函数std::string getName() const
。使用STL算法我想计算向量中Person
返回“Chad”的所有getName()
个对象。
简单地遍历循环的行为将是:
int num_chads = 0;
for(std::vector<Person *>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
if((*it)->getName() == "Chad")
++num_chads;
}
我想重做这个,所以它使用所有STL算法和仿函数等(使其更加面向功能)。这就是我认为我需要做的事情:
const int num_chads = std::count_if(vec.begin(), vec.end(),
std::bind1st(std::bind2nd(std::equal_to, mem_fun(Person::getName)), "Chad"));
你可能会说这不起作用。首先,据我所知,你不能在binder1st / binder2nd对象上使用bind1st / bind2nd,因为它们专门用于与std::binary_functions
一起使用。其次,更重要的是,我认为我没有使用正确的技术。我做想要将其中一个参数绑定到“Chad”,但是使用iterator参数我实际上只想在调用equals_to
的绑定版本之前将迭代器值转换为字符串。
我认为使用Boost可以做到这一点,但是可以只使用核心C ++ 03(即没有C ++ 0x lambas!)?
编辑:任何人都可以提出一个不使用用户定义的谓词的例子(即只使用std工具包中提供的工具)吗?
编辑:虽然Matthieu的答案是关于如何在STL算法中使用仿函数的教科书答案,但Cubbi的答案来自我正在寻找的方法(虽然Mathieu在我编辑问题之前做了回答以使其更具体,所以在那里道歉!)。答案 0 :(得分:9)
我一直觉得lambda相对难以辨认。我更喜欢写明确的类型:
struct Named
{
Named(char const* ref): _ref(ref) {}
bool operator()(Person* p) const { return p && p->getName() == _ref; }
char const* _ref;
};
size_t const c = std::count_if(vec.begin(), vec.end(), Named("Chad"));
虽然Named
的定义是“不符合”的,但正确选择的名称表达了意图并隐藏了实现细节。就个人而言,我认为这是一件好事,因为那样我就不会分散实现细节,也不会试图通过对代码进行逆向工程来弄清楚是什么(尽管可能很明显)。
答案 1 :(得分:5)
由于没有人发布实际的提升代码,C ++ 98 with boost:
ptrdiff_t num_chads = std::count_if(vec.begin(), vec.end(),
boost::bind(&Person::getName, _1) == "Chad");
对于纯C ++,我不认为没有compose1
适配器,在STL中存在但在C ++ stdlib中不存在...
这里是(使用GCC的STL实现)
ptrdiff_t num_chads = std::count_if(vec.begin(), vec.end(),
__gnu_cxx::compose1(
std::bind2nd(std::equal_to<std::string>(), "Chad"),
std::mem_fun(&Person::getName)));
编辑:已更正为Person*
答案 2 :(得分:1)
使用boost::bind
,它在某种程度上优于现有的标准绑定机制。 boost::bind
完全兼容C ++ 03。