Re: Using an ostream_iterator over pairs
On Jan 21, 9:27 pm, ShaunJ <sjack...@gmail.com> wrote:
I'm trying to use an ostream_iterator to iterate over a set of pairs.
I've used an ostream_iterator over other types and had no problem.
However, with the following code snippet, I'm getting a compiler
error, and I'm stymied as to why. It's seems to be related to the
string type, because iterating over pairs of other types has worked
fine for me. The (rather verbose) error is:
/usr/include/c++/4.2/bits/stream_iterator.h:196: error: no match for
'operator<<' in '*((std::ostream_iterator<std::pair<unsigned int,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >>, c=
har, std::char_traits<char> >*)this)-
std::ostream_iterator<std::pair<unsigned int, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >, char,
std::char_traits<char> >::_M_stream << __value'
#include <iostream>
#include <iterator>
#include <set>
#include <string>
using namespace std;
I'm dubious about the following operator. It's in the global
namespace, but none of its parameters depend on the global
namespace, so it won't be found during dependent name lookup.
ostream& operator <<(ostream& o, const pair<unsigned, string>& age)
{
return o << age.second << ": " << age.first;
}
int main()
{
string a("Alice");
string b("Bob");
string c("Carol");
pair<unsigned, string> pa(19, a);
pair<unsigned, string> pb(17, c);
pair<unsigned, string> pc(23, b);
set<pair<unsigned, string> > ages;
ages.insert(pa);
ages.insert(pb);
ages.insert(pc);
And dependent name lookup is what will be used here, in the
function std::copy, in the instantiation of ostream_iterator.
ostream_iterator<pair<unsigned, string> > oi(cout, ", ");
copy(ages.begin(), ages.end(), oi);
cout << '\n';
return 0;
}
The usual solution is to define some specific type to be output.
Something like:
class Whatever
{
public:
// ...
friend std::ostream&operator<<(
std::ostream& dest, Whatever const& obj ) ;
private:
unsigned u ;
std::string n ;
} ;
If you really want to use pair (which is rarely a good idea),
then it's pretty simple to create a wrapper class for it:
class WrappedPair
{
public:
WrappedPair( std::pair< unsigned, std::string > const& obj )
: myObj( &obj )
{
}
friend std::ostream&operator<<(
std::ostream& dest,
WrappedPair const&
obj )
{
return dest << obj->myObj.second << ": " << obj-
myObj.first ;
return dest ;
}
private:
std::pair< unsigned, std::string > const*
myObj ;
} ;
Then:
std::copy( ages.begin(), ages.end(),
std::ostream_iterator< WrappedPair >( std::cout, ",
" ) ) ;
But seriously, a user defined class (with e.g. members age and
name, rather than first and second) is probably more what you
want to begin with.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34