返回STL容器上的循环以使用功能技术

Chr*_*lin 8 c++ functional-programming currying

我有一个std::vector指针Person对象,它们具有成员函数std::string getName() const.使用STL算法我想计算Person向量中getName()返回"Chad"的所有对象.

简单地遍历循环的行为将是:

int num_chads = 0;
for(std::vector<Person *>::const_iterator it = vec.begin(); it != vec.end(); ++it)
{
    if((*it)->getName() == "Chad")
        ++num_chads;
}
Run Code Online (Sandbox Code Playgroud)

我想重做这个,所以它使用所有STL算法和仿函数等(使其更加面向功能).这是我认为我需要做的事情:

const int num_chads = std::count_if(vec.begin(), vec.end(),
                                    std::bind1st(std::bind2nd(std::equal_to, mem_fun(Person::getName)), "Chad"));
Run Code Online (Sandbox Code Playgroud)

你可能会说这不起作用.首先,据我所知,你不能在binder1st/binder2nd对象上使用bind1st/bind2nd,因为它们是专门设计用的std::binary_functions.其次,更重要的是,我认为我没有使用正确的技术.我确实希望将其中一个参数绑定到"Chad",但是使用iterator参数我实际上只是想在调用绑定版本之前将迭代器值转换为字符串equals_to.

我认为使用Boost可以做到这一点,但是可能只使用核心C++ 03(即没有C++ 0x lambas!)?

编辑:任何人都可以提出一个不使用用户定义的谓词的例子(即只使用std工具包中提供的工具)?

编辑:虽然Matthieu的答案是关于如何在STL算法中使用仿函数的教科书答案,但Cubbi的答案来自我正在寻找的方法(尽管Mathieu在编辑问题之前确实回答了它以使其更具体,所以在那里道歉!).

Mat*_* M. 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"));
Run Code Online (Sandbox Code Playgroud)

虽然定义Named是"脱节",但正确选择的名称表达了意图并隐藏了实现细节.就个人而言,我认为这是一件好事,因为那时我不会分散实现细节或试图通过逆向工程代码来弄清楚是什么(尽管可能很明显).


Cub*_*bbi 5

由于没有人发布实际的提升代码,C++ 98 with boost:

ptrdiff_t num_chads = std::count_if(vec.begin(), vec.end(),
                      boost::bind(&Person::getName, _1) == "Chad");
Run Code Online (Sandbox Code Playgroud)

测试运行https://ideone.com/PaVJe

对于纯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)));
Run Code Online (Sandbox Code Playgroud)

测试运行:https://ideone.com/EqBS5

编辑:更正为帐户 Person*