 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Siegfried Heintze Guest
|
Posted: Tue May 02, 2006 11:06 am Post subject: How to copy maps to ostream_iterators? |
|
|
I have the following code that I am trying to compile with g++ 3.2 (see
below).
The syntax error messages are telling me there is no function operator<<
defined to accept a std::pair. This is not true: as you can see I have
defined such a function. I've seen this work with other compilers. I've
tried
std::ostream& operator<<(std::ostream&os, const
std::pair<std::string,std::string>&x){ .... }
but that does not work either.
Can anyone tell me what I am doing wrong?
Thanks,
Siegfried
template <typename K, typename V>
inline std::ostream& operator<<(std::ostream& os, const std::pair<K,V>& x)
{
return os << "[" << x.first << ","<< x.second << "]";
}
std::map<std::string,std::string> m;
std::string hello="hello", world="world";
m[hello]=world;
std::copy(m.begin(),m.end(),
std::ostream_iterator<std::pair<std::string,std::string> >(std::cout));
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Tue May 02, 2006 9:06 pm Post subject: Re: How to copy maps to ostream_iterators? |
|
|
"Siegfried Heintze" <siegfried (AT) heintze (DOT) com> writes:
| Quote: | I have the following code that I am trying to compile with g++ 3.2
(see below).
The syntax error messages are telling me there is no function
operator<< defined to accept a std::pair.
|
Syntax errors? I'd expect to see something like "no match". The syntax
seems ok, though.
| Quote: | This is not true: as you can see I have defined such a function.
|
But not in the right namespace. Argument dependent lookup causes it to
be looked up in namespace std; and only there, because some overloads
of operator<< are found there.
| Quote: | I've seen this work with other compilers. I've tried
std::ostream& operator<<(std::ostream&os, const
std::pair<std::string,std::string>&x){ .... }
but that does not work either.
Can anyone tell me what I am doing wrong?
Thanks,
Siegfried
template <typename K, typename V
inline std::ostream& operator<<(std::ostream& os, const std::pair<K,V>& x)
{
return os << "[" << x.first << ","<< x.second << "]";
}
std::map<std::string,std::string> m;
std::string hello="hello", world="world";
m[hello]=world;
std::copy(m.begin(),m.end(),
std::ostream_iterator<std::pair<std::string,std::string> >(std::cout));
|
The value_type of this map type is
std::pair<std::string const, std::string>, which is different from the
type you use.
The following program compiles:
#include <map>
#include <algorithm>
#include <iostream>
#include <ostream>
#include <iterator>
namespace std
{
template <typename K, typename V>
inline std::ostream& operator<<(std::ostream& os, std::pair<K,V> const & x)
{
return os << "[" << x.first << "," << x.second << "]";
}
}
int main()
{
typedef std::map<std::string,std::string> map_type;
map_type m;
std::string hello("hello");
std::string world("world");
m[hello] = world;
std::copy(m.begin(),m.end(),
std::ostream_iterator<map_type::value_type>(std::cout));
}
The problem is that strictly speaking, it has undefined behavior,
because we mere users are not allowed to do anything in namespace std
other than provide specializations of Standard templates for our own
types.
What about
#include <map>
#include <algorithm>
#include <iostream>
#include <ostream>
#include <iterator>
template <typename pair_type>
struct pair_printer
{
void operator()(pair_type const & x)
{
std::cout << "[" << x.first << ","<< x.second << "]";
}
};
int main()
{
typedef std::map<std::string,std::string> map_type;
map_type m;
std::string hello("hello");
std::string world("world");
m[hello] = world;
std::for_each(m.begin(),m.end(),
pair_printer<map_type::value_type>());
}
?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Wed May 03, 2006 10:06 am Post subject: Re: How to copy maps to ostream_iterators? |
|
|
In article <4456d1ff@mamba.>, Siegfried Heintze <siegfried (AT) heintze (DOT) com>
wrote:
| Quote: | The syntax error messages are telling me there is no function operator
defined to accept a std::pair. This is not true:
|
Its true since operator << ()'s args are in namespace std and operator
<< is called from namespace std [in std::ostream_iterator<...>()
lookup only occurs in namespace std.
| Quote: | as you can see I have
defined such a function. I've seen this work with other compilers. I've
tried
std::ostream& operator<<(std::ostream&os, const
std::pair<std::string,std::string>&x){ .... }
but that does not work either.
1) use for_each |
class print_one
{
std::ostream &os;
public:
print_one(std::ostream &a) s(a){}
void operator () (const std::pair<const
std::string,std::string> &p)
{
// print as ostream_iterator would have
}
};
for_eacn(m.begin(),m.end(),print_one(std::cout));
2) write an output iterator to handle std::pair outside of namespace
std.
3) STRICTLY ILLEGAL in terms of the standard. put your operator << ()
in namespace std.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Thu May 04, 2006 9:22 pm Post subject: Re: How to copy maps to ostream_iterators? |
|
|
Carl Barron wrote:
| Quote: | In article <4456d1ff@mamba.>, Siegfried Heintze
siegfried (AT) heintze (DOT) com> wrote:
The syntax error messages are telling me there is no
function operator<< defined to accept a std::pair. This is
not true:
Its true since operator << ()'s args are in namespace std and
operator << is called from namespace std [in
std::ostream_iterator<...>() lookup only occurs in namespace
std.
as you can see I have defined such a function. I've seen
this work with other compilers. I've tried
std::ostream& operator<<(std::ostream&os, const
std::pair<std::string,std::string>&x){ .... }
but that does not work either.
|
It might be worth pointing out that the reason it works with
older compilers is that they don't use two phase lookup. It
will still work with modern compilers outside of a template. It
is only when instantiating a template that lookup is restricted
to ADL. And then only for dependant names, and for the lookup
which takes place in the instantiation context.
[...]
| Quote: | 3) STRICTLY ILLEGAL in terms of the standard. put your
operator << () in namespace std.
|
Illegal, but it will work everywhere.
More importantly, of course, overloading an operator<< for any
standard class is something that you would never want to do
outside of small experimental programs. Why should your
component get the priviledge, and no other?
My usual solution for this sort of thing is a class which
implicitly converts to or from the standard type. In this case,
something along the lines of:
class MyPair
{
public:
MyPair( map_type::value_type const& v ) : myValue( v ) {}
friend std::ostream& operator<<( std::ostream& dest,
MyPair const& obj ) ;
private:
map_type::value_type myValue ;
} ;
Something along the lines of:
std::copy( m.begin(), m.end(),
std::ostream_iterator< MyPair >( std::cout ) ) ;
Should then do the job.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|