C++ For_each和指向成员函数的指针

C++ For_each和指向成员函数的指针,c++,stl,C++,Stl,我遇到了以下代码的问题: #include <list> #include <algorithm> #include <string> #include <iostream> #include <functional> using namespace std; struct Person { string name; ostream& print(ostream& out) const {

我遇到了以下代码的问题:

#include <list>
#include <algorithm>
#include <string>
#include <iostream>
#include <functional>
using namespace std;

struct Person {
    string name;
    ostream& print(ostream& out) const {
        return out << name;
    }
};

int main()
{
    Person p = { "Mark" };
    list<Person> l;
    l.push_back(p);
    for_each(l.begin(), l.end(), bind(&Person::print, std::placeholders::_1, std::cout)); // this placeholder is not a pointer so it can't work anyways

    // I also tried something with lambdas like this but it doesn't work either
    //for_each(l.begin(), l.end(), bind([](Person& p, ostream& out) { mem_fun(&Person::print)(&p, out); }, std::placeholders::_1, cout));

    // it doesn't even work that way
    //for_each(l.begin(), l.end(), bind([](Person& p, ostream& out) { p.print(out); }, std::placeholders::_1, cout));
}
每种情况下都有一条错误消息

microsoft visual studio 12.0\vc\include\tuple(80): error C2248: 'std::basic_ostream<char,std::char_traits<char>>::basic_ostream' : cannot access protected member declared in class 'std::basic_ostream<char,std::char_traits<char>>'
我想知道引擎盖下面是什么,为什么不起作用。它所说的是什么受保护的成员?

您的for\u每个调用和关联的绑定都在尝试复制std::cout,而不管打印本身引用了什么,这是不可能的,因为流是不可复制的

在C++03中,强制其不可复制性的唯一方法是将其复制构造函数声明为受保护的或私有的,因此您会看到错误

改为传递std::cout。

如果希望通过引用将std::cout传递给打印函数,则需要使用。否则,将尝试复制它,因为std::for_都按值获取其函子参数,并且std::cout的类型不可复制:1

1您看到的关于受保护副本构造函数不可访问的消息是由于在您使用的标准库的实现中,通过使类的副本构造函数非公共来实现不可复制性。这是在C++03中实现不可复制性的唯一方法-自C++11以来,惯用的方法是将复制构造函数定义为已删除。

问题是std::bind表达式将导致生成其参数的副本。std::cout不是来自可复制类型,因此出现错误。您可以通过传递std::reference\u包装来解决这个问题。您可以使用std::ref制作其中一个:


非常感谢,这基本上解决了问题,但我还有另一个问题,现在甚至这个for_each也适用于_eachl.begin、l.end、bind&Person::print、std::placeholders::_1、std::cout;但是为什么呢?占位符被一个对象代替了,不是指针吗?@greenshade:这和你的问题中的调用是一样的,你说它不起作用。是哪一个?无论如何,如果你还有其他问题,请发布另一个问题!:是的,但我的意思是,取消引用迭代器将返回一个对象,而不是指向对象的指针,因此在作为第一个参数传递给&Person::print之后,应该是一个错误?还是不@格林沙德:我不明白你在问什么。什么迭代器?在遍历_的列表时,每个迭代器都使用迭代器。我说的是这个迭代器。有什么理由需要使用bind而不能只使用lambda:[]const Person&p{p.printcout;}?事实上,在这些情况下,我发现基于范围的for循环比for_each:forconst auto&p:lp.printcout;}更简洁
for_each(l.begin(), 
         l.end(), 
         bind(&Person::print, std::placeholders::_1,  std::ref(std::cout));
//                                                    ^^^^^^^^^^^^^^^^^^^
for_each(l.begin(), l.end(), 
         bind(&Person::print, std::placeholders::_1, std::ref(std::cout)));
                                                     ^^^^^^^^