问题
Thanks for giving comments to the following.
Class1 { debug(std::ostream&){} };
int main() {
std::vector<Class1*> list1;
// some work to do
}
Target Platform:
- Platform(1): Win 7x64, VS2010
- Platform(2): Linux x32, g++ 4.4
Q: What should be the correct way to pass "std::cout" to following statement?
std::for_each(list1.begin(),
list1.end(),
"afunction(&Class1::debug, std::cout)");
I previously used "std::cout" inside the debug() function, but later consider to give flexibility for the output of debug message.
Edit: More information: if functor objects is the way to go, how should I implements the functor to cope with multiple classes (those classes have no relationship except the same "debug" function signature)?
Edit(2): Using "std::for_each", is it possible to destroy all objects in list1 by invoking the corresponding destructor for each class directly? (e.g. for_each(l.begin(), l.end(), "Class::~Class1");
Edit(3): As per "pmr" suggested, I make the statement as
std::for_each(l.begin(),
l.end(),
std::bind2nd(std::mem_fn(&Class1::debug), out) );
It compiles and run correctly on linux platform, but failed on VS2010, the code for Class1::debug is
void Class1::debug(const std::ostream& out)
{
out << "some text" << someVar << "some text" << std::endl;
}
The VS error msg is
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'const std::ostream' (or there is no acceptable conversion)
Any cue?
[Closed] I now implemented the overloaded operator << for my classes, and the use of debug print function is closed. Thanks very much for all hints given.
回答1:
Since you are using g++ 4.4 you can't use lambda expressions which would be the first choice (later versions support them, MSVC does as well).
So you need a functor. A functor is a function object, that is a class (or struct) that implements operator()
. Like this:
class Debug
{
public:
Debug(ostream& os) : _os(os)
{ }
void operator()(Class1* instance)
{
// will print the pointer, replace with user code
os << instance << endl;
}
private:
ostream& _os;
};
Use like this:
Debug d(cout);
std::for_each(list1.begin(), list1.end(), d);
回答2:
use lambda instead of function pointers. This is a feature of C++11x and you need to include a flag for compiler to recognise lambda.
std::for_each(list1.begin(), list1.end(), [&debug, &cout]
{
// implementaion
}
);
回答3:
As GCC does not support lambdas until 4.5, the clearest solution is out of the question.
The second easiest solution when you want to use a lot of generic algorithms is Boost.Lambda http://www.boost.org/doc/libs/1_49_0/doc/html/lambda.html:
for_each(list1.begin(), list.end(), _1->debug(cout));
And finally, the tedious functor solution:
class Output
{
public:
explicit Output(ostream& ios) : os(&ios)
{
}
void operator()(Class1* obj)
{
obj->debug(*os);
}
private:
ostream* os;
};
for_each(list1.begin(), list1.end(), Output(cout));
Personally I think that without C++11 lambdas or Boost Lambdas, for_each is more pain than it's worth. Might as well do a simple loop:
for (vector<Class1*>::iterator it = list1.begin(); it != end; ++it)
(*it)->debug(cout);
回答4:
C++03:
#include <vector>
#include <functional>
#include <iostream>
#include <algorithm>
struct Foo {
void debug(std::ostream&) {}
};
int main()
{
std::vector<Foo*> foos;
std::for_each(foos.begin(), foos.end(),
std::bind2nd(std::mem_fun(&Foo::debug), std::cout));
return 0;
}
Please note that the binders have been deprecated and boost::bind
or
C++11 should be favored. You should really get a newer compiler.
来源:https://stackoverflow.com/questions/9530859/member-function-to-a-list-of-pointer