Because of your comment I am a new programmer and am experimenting with different ideas, I'm posting this answer as an alternative approach which also shows some algorithm that you might enthusiastic about.
I think that std::copy
isn't the right tool if what you want to do is both
- calling a member function on the objects in a collection, and only after that
- copying/printing them to screen
One, and maybe the best, approach is the one in the atru's answer, which basically solves only point 2 with std::copy
(and this is something you already knew how to do it, based on your question), and point 1 by overloading <<
, which makes the trick.
The alternative I propose is based on the idea that "calling a member function on every object of a collection" is actually a transform operation of that collection. std::transform
, however, just like std::copy
acts on iterators, not on ranges, so they cannot be easily composed with one another.
Here comes Boost, with boost::copy
and boost::adaptors::transformed
which allow you to do this:
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
where vectNames
is "piped into" transformed
, which applies the lambda on every element of the collection, resulting in a new temporary collection, which is the argument to boost::copy
. If you were to use std::copy
, you would have to store the temporary somewhere, e.g. in temp
, before passing to std::copy
its iterators temp.begin()
and temp.end()
.
The full example is below. I hope it will give you some insight in different, more functional, approaches.
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
};
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
using boost::adaptors::transformed;
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
}