using for_each
-
I have this explicit loop:
FileMap::iterator it;
for (it = outputFiles.begin(); it != outputFiles.end(); it++)
{
it->second->close();
}where FileMap is a map<string,ofstream*>, so the loop is just going through all the stream pointers and calling close() on them is it possible to implement this using for_each?, I tried this but got compiler errors:
for_each(outputFiles.begin(), outputFiles.end(), std::mem_fun(&std::ofstream::close));
-
I have this explicit loop:
FileMap::iterator it;
for (it = outputFiles.begin(); it != outputFiles.end(); it++)
{
it->second->close();
}where FileMap is a map<string,ofstream*>, so the loop is just going through all the stream pointers and calling close() on them is it possible to implement this using for_each?, I tried this but got compiler errors:
for_each(outputFiles.begin(), outputFiles.end(), std::mem_fun(&std::ofstream::close));
-
I have this explicit loop:
FileMap::iterator it;
for (it = outputFiles.begin(); it != outputFiles.end(); it++)
{
it->second->close();
}where FileMap is a map<string,ofstream*>, so the loop is just going through all the stream pointers and calling close() on them is it possible to implement this using for_each?, I tried this but got compiler errors:
for_each(outputFiles.begin(), outputFiles.end(), std::mem_fun(&std::ofstream::close));
Yes, it is doable, but not using 'clean' STL design ideas. remember that the type of the element in the map is std::pair<string,ofstream*>, not just ofstream or ofstream*, so you need to compensate for that. The easiest way I can think of is to use lambda expressions (see boost::lambda for a comprehensive library). Personally, I feel that lambda libraries are shakey ground at the moment. Most developers have enough trouble reading normal STL constructs without adding in strange things like '_1'and '_2' - but it depends on how comfortable with STL you and your co-workers are. Just as an aside, are you sure that you really want to do this? Assuming that you dynamically creating the files why don't you rely upon the destructors to close the files for you - if this is the behavior that you want use boost::shared_ptr to keep a reference counter handle to the files, and when the map goes out of scope, all the files will be taken with it. The only other reason I can think that you would want to do this is to reuse the files, if you are doing this make sure that you test thoroughly Herb Sutter (the convenor of the C++ standards committee) documented some interesting 'features' (read: issues) of ofstream's after they have recycled in a recent issue of the C/C++ Users Journal. After all that, if you're prepared to compromise on a 'dirty' rewrite for_each to work nicely with pairs, use the normal loop or try the following:
void closer(const std::pair<string,ofstream*>& toClose) { toClose.second->close(); } for_each(outputFiles.begin(), outputFiles.end(), closer);
In this case I think your original loop really does make things a lot clearer than it would otherwise be.
If you can keep you head when all about you Are losing theirs and blaming it on you; If you can dream - and not make dreams your master; If you can think - and not make thoughts you aim; Yours is the Earth and everything that's in it. Rudyard Kipling
-
Yes, it is doable, but not using 'clean' STL design ideas. remember that the type of the element in the map is std::pair<string,ofstream*>, not just ofstream or ofstream*, so you need to compensate for that. The easiest way I can think of is to use lambda expressions (see boost::lambda for a comprehensive library). Personally, I feel that lambda libraries are shakey ground at the moment. Most developers have enough trouble reading normal STL constructs without adding in strange things like '_1'and '_2' - but it depends on how comfortable with STL you and your co-workers are. Just as an aside, are you sure that you really want to do this? Assuming that you dynamically creating the files why don't you rely upon the destructors to close the files for you - if this is the behavior that you want use boost::shared_ptr to keep a reference counter handle to the files, and when the map goes out of scope, all the files will be taken with it. The only other reason I can think that you would want to do this is to reuse the files, if you are doing this make sure that you test thoroughly Herb Sutter (the convenor of the C++ standards committee) documented some interesting 'features' (read: issues) of ofstream's after they have recycled in a recent issue of the C/C++ Users Journal. After all that, if you're prepared to compromise on a 'dirty' rewrite for_each to work nicely with pairs, use the normal loop or try the following:
void closer(const std::pair<string,ofstream*>& toClose) { toClose.second->close(); } for_each(outputFiles.begin(), outputFiles.end(), closer);
In this case I think your original loop really does make things a lot clearer than it would otherwise be.
If you can keep you head when all about you Are losing theirs and blaming it on you; If you can dream - and not make dreams your master; If you can think - and not make thoughts you aim; Yours is the Earth and everything that's in it. Rudyard Kipling
-
I have this explicit loop:
FileMap::iterator it;
for (it = outputFiles.begin(); it != outputFiles.end(); it++)
{
it->second->close();
}where FileMap is a map<string,ofstream*>, so the loop is just going through all the stream pointers and calling close() on them is it possible to implement this using for_each?, I tried this but got compiler errors:
for_each(outputFiles.begin(), outputFiles.end(), std::mem_fun(&std::ofstream::close));
There is another thing you could add to Andrew's answer, without pulling in "weird lambda" stuff. This is what I'd do. Add a function called
select_second
like this:template <typename TPair>
struct select_second : public std::unary_function<TPair, typename TPair::second_type> {
result_type operator()(argument_type p) const {
return p.second;
}
};then add a composer function like this:
// It takes 2 functors, f and g, and compose them into f o g, i.e., f(g(x))
template <typename F, typename G>
struct composed_fn : public std::unary_function<typename G::argument_type, typename F::result_type> {
const G& g;
const F& f;
composed_fn(const F& f_, const G& g_) : g(g_), f(f_) { }result_type operator()(argument_type x) const {
return f(g(x));
}
};template <typename F, typename G>
composed_fn<F, G> compose(const F& f, const G& g) {
return composed_fn<F, G>(f, g);
}Then you ought to be able to do something like:
for_each(outputFiles.begin(), outputFiles.end(), compose(std::mem_fun(&std::ofstream::close), select_secondFileMap::value\_type()));
I'm not sure if functional composition is possible in boost without the use of the "obscure" lambda library. If it is, please use boost instead. It's good and solid code. However, I've used this code myself for a while, and I've found it to be useful. It's easy to follow and understand if you have a grasp of templates and functors. f(g(x)) shouldn't be a surprise to anyone, it's basic high school mathematics. :) -- Booohoo!
-
There is another thing you could add to Andrew's answer, without pulling in "weird lambda" stuff. This is what I'd do. Add a function called
select_second
like this:template <typename TPair>
struct select_second : public std::unary_function<TPair, typename TPair::second_type> {
result_type operator()(argument_type p) const {
return p.second;
}
};then add a composer function like this:
// It takes 2 functors, f and g, and compose them into f o g, i.e., f(g(x))
template <typename F, typename G>
struct composed_fn : public std::unary_function<typename G::argument_type, typename F::result_type> {
const G& g;
const F& f;
composed_fn(const F& f_, const G& g_) : g(g_), f(f_) { }result_type operator()(argument_type x) const {
return f(g(x));
}
};template <typename F, typename G>
composed_fn<F, G> compose(const F& f, const G& g) {
return composed_fn<F, G>(f, g);
}Then you ought to be able to do something like:
for_each(outputFiles.begin(), outputFiles.end(), compose(std::mem_fun(&std::ofstream::close), select_secondFileMap::value\_type()));
I'm not sure if functional composition is possible in boost without the use of the "obscure" lambda library. If it is, please use boost instead. It's good and solid code. However, I've used this code myself for a while, and I've found it to be useful. It's easy to follow and understand if you have a grasp of templates and functors. f(g(x)) shouldn't be a surprise to anyone, it's basic high school mathematics. :) -- Booohoo!
Thanks Jörgen, answers like this are why I love CodeProject, fully deserving of a five. Time to go back and fix some of that old code... Boost::Compose[^] Has been deprecated in favour of bind and lambda btw :)
If you can keep you head when all about you Are losing theirs and blaming it on you; If you can dream - and not make dreams your master; If you can think - and not make thoughts you aim; Yours is the Earth and everything that's in it. Rudyard Kipling
-
Thanks Jörgen, answers like this are why I love CodeProject, fully deserving of a five. Time to go back and fix some of that old code... Boost::Compose[^] Has been deprecated in favour of bind and lambda btw :)
If you can keep you head when all about you Are losing theirs and blaming it on you; If you can dream - and not make dreams your master; If you can think - and not make thoughts you aim; Yours is the Earth and everything that's in it. Rudyard Kipling
Thanks for your kind words. :) Real soon now, I will be ending a java project (at least my involvement in it), and go straight back to C++. I can't wait. ;) I have a bunch of header files with code for dealing with composition. With a bit of luck, I'll see if I can gather enough strength and will to write an article about it later on. Sure, there's always boost, but I figure I can show the concepts of functional composition if I used my own code. I think just the awareness of these tricks makes STL a lot easier and more enjoyable to work with. -- Booohoo!