Reputation: 8920
I have the following vector:
std::vector<std::pair<int,std::string>> songs;
I want to use std::copy to pass elements from the vector (let's say the int) to ostream, something like the following which ofcourse doesn't work:
std::copy(songs.begin(),songs.end(),std::ostream_iterator<int>(std::cout,""));
I know that I can do it with this way:
for(auto it=songs.begin(); it!=songs.end(); ++it)
{
std::cout << (*it).first;
}
But I am wondering if it possible in C++ to create an iterator that points only to one of the elements of the pair and then use it to iterate and copy the elements to ostream or how can I make the std::copy above work?
Upvotes: 1
Views: 4101
Reputation: 109119
As chris mentioned in the comments, the easiest solution is to use std::transform
std::transform( songs.begin(), songs.end(),
std::ostream_iterator<int>( std::cout, "\n" ),
[]( decltype(v)::value_type const& p ) -> decltype(p.first) {
return p.first;
}
);
If you want to go the custom iterator route, create a type that mimics ostream_iterator
's behavior, and additionally uses std::get
to retrieve only the item you care about.
template<std::size_t N>
struct get_tuple_item_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
get_tuple_item_iterator( std::ostream& os, std::string term )
: os_(os)
, term_(std::move(term))
{}
template<typename... T>
get_tuple_item_iterator& operator=( std::tuple<T...> const& elem )
{
static_assert(N < sizeof...(T), "N is out of range");
os_ << std::get<N>( elem ) << term_;
return *this;
}
template<typename T1, typename T2>
get_tuple_item_iterator& operator=( std::pair<T1, T2> const& elem )
{
static_assert((N == 0) || (N == 1), "N must be 0 or 1 for std::pair");
return operator=( std::tie( elem.first, elem.second ) );
}
get_tuple_item_iterator& operator*() { return *this; }
get_tuple_item_iterator& operator++() { return *this; }
get_tuple_item_iterator& operator++( int ) { return *this; }
private:
std::ostream& os_;
std::string term_;
};
Use it as
std::copy( songs.begin(), songs.end(),
get_tuple_item_iterator<0>( std::cout, "\n" ) );
Upvotes: 6