 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Ivan Korotkov Guest
|
Posted: Sun Aug 29, 2004 11:06 am Post subject: Overloading operator<< on std::pair<> |
|
|
Hello everybody,
why can't I compile this:
#include <iostream>
#include <utility>
using namespace std;
ostream &operator<<(ostream &ostr, const pair
{
return (ostr << val.first << ' ' << val.second.c_str());
}
int main()
{
ostream_iterator oi(cout);
*oi = pair<int, string>(1, "a");
return 0;
}
Compiler reports something like:
iterator(257) : error C2679: binary '<<' : no operator found which takes a
right-hand operand of type 'const std::pair<_Ty1,_Ty2>' (or there is no
acceptable conversion)
with
[
_Ty1=int,
_Ty2=std::string
]
What's wrong with my code?
Thanks,
--
Ivan
[ 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: Sun Aug 29, 2004 10:41 pm Post subject: Re: Overloading operator<< on std::pair<> |
|
|
Ivan Korotkov <koroNOSPAMtkov2 (AT) ztelDOT (DOT) ru> wrote:
| Quote: | why can't I compile this:
#include <iostream
#include
using namespace std;
ostream &operator<<(ostream &ostr, const pair
{
return (ostr << val.first << ' ' << val.second.c_str());
}
int main()
{
ostream_iterator oi(cout);
*oi = pair<int, string>(1, "a");
return 0;
}
I forget the name of the process, but the search space for overloads |
is the union of namespaces of the arguments. In this case std. [using
namespace std, does not remove things from std, only lets you refer to
them in the global namespace] therefore since there is no operator <<
(std::ostream &,std::pair
find your operator << overload.
Workarounds:
1) struct my_pair:std::pair
{
my_pair(int a,const std::string &b)
:std::pair<int,string>(a,b){}
};
inline operator << (std::ostream &os,const my_pair &p)
{
return os << p.first << ' ' << p.second;
}
declare your pairs as my_pairs.
2) class print
{
std::pair
public:
print(std::pair<int,std::string> const &a):p(a){}
std::ostream & operator () (std::ostream &os)
{
return os << p.first << ' ' << p.second;
};
};
use the manipulator like os << print(the_pair);
3) cheat [not recommended in general] and put your operator in
namespace std.
4) do not use operator << directly on std::pair's.
5) use boost::tuple which does provide operator <<'s. [Or
tr1::tuples, if available]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Korotkov Guest
|
Posted: Mon Aug 30, 2004 10:51 am Post subject: Re: Overloading operator<< on std::pair<> |
|
|
| Quote: | I forget the name of the process, but the search space for overloads
is the union of namespaces of the arguments. In this case std. [using
namespace std, does not remove things from std, only lets you refer to
them in the global namespace] therefore since there is no operator
(std::ostream &,std::pair<T1,T2> const &); in namespace std it does not
find your operator << overload.
|
Thanks! This really helped. So I guess _this_ is what is called Koenig
lookup? I thought that it specifies that namespaces of argument types
should be _included_ in search space, but I didn't think that global space
is excluded. Thank you again!
--
Ivan
e-mail me at: korotkov2 at ztel dot ru
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Mon Aug 30, 2004 10:55 am Post subject: Re: Overloading operator<< on std::pair<> |
|
|
On 29 Aug 2004 07:06:47 -0400, Ivan Korotkov
<koroNOSPAMtkov2 (AT) ztelDOT (DOT) ru> wrote:
| Quote: | why can't I compile this:
#include <iostream
#include
|
#include
You need that for ostream_iterator. Your compiler may let you get
by without it, but others will not.
| Quote: | using namespace std;
|
namespace std { // This is forbidden but must be used to make it work.
| Quote: | ostream &operator<<(ostream &ostr, const pair
{
return (ostr << val.first << ' ' << val.second.c_str());
}
|
}
| Quote: | int main()
{
ostream_iterator oi(cout);
*oi = pair<int, string>(1, "a");
return 0;
}
Compiler reports something like:
iterator(257) : error C2679: binary '<<' : no operator found which takes a
right-hand operand of type 'const std::pair<_Ty1,_Ty2>' (or there is no
acceptable conversion)
What's wrong with my code?
|
Because ostream_iterator is in namespace std, the search for the
operator<< used in ostream_iterator::operator= starts in that
namespace. Many operator<< are found in that namespace terminating
the search. They hide your global operator.
"It is undefined for a C++ program to add declarations or definitions
to namespace std ...". There are exceptions, but the above function
is not one of them. The only result of the undefined that I have
seen is works fine.
If you dislike that hack, you can write your own PairIntString and
write the function for that. Since your PairIntString and your
operator<< will be in either your own namespace or the global one,
ADL will find the operator.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
llewelly Guest
|
Posted: Mon Aug 30, 2004 11:42 pm Post subject: Re: Overloading operator<< on std::pair<> |
|
|
[email]cbarron3 (AT) ix (DOT) netcom.com[/email] (Carl Barron) writes:
| Quote: | Ivan Korotkov <koroNOSPAMtkov2 (AT) ztelDOT (DOT) ru> wrote:
why can't I compile this:
#include <iostream
#include
using namespace std;
ostream &operator<<(ostream &ostr, const pair
{
return (ostr << val.first << ' ' << val.second.c_str());
}
int main()
{
ostream_iterator oi(cout);
*oi = pair<int, string>(1, "a");
return 0;
}
I forget the name of the process, but the search space for overloads
is the union of namespaces of the arguments.
[snip] |
This is called ADL, short for Andrew's Devious Lookup. :-)
Seriously, some call it Koenig lookup, because a guy named Andrew
Koening invented it. The standard calls it Argument Dependent
Lookup, which gives a nice hint as to what it does, and most
people call it ADL, which is short Argument Dependent Lookup.
But ADL isn't the only thing happening here. It is the resolution of
depenendent names (also called two-phase lookup) which determines
that only ADL will be used to find cannidate functions for the
use(s) of operator<< inside the operator= template.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ivan Korotkov Guest
|
Posted: Tue Aug 31, 2004 7:56 pm Post subject: Re: Overloading operator<< on std::pair<> |
|
|
| Quote: | But ADL isn't the only thing happening here. It is the resolution of
depenendent names (also called two-phase lookup) which determines
that only ADL will be used to find cannidate functions for the
use(s) of operator<< inside the operator= template.
|
And what else can be used? Is there some info source I need to take a look
at?
--
Ivan
e-mail me at: korotkov2 at ztel dot ru
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
llewelly Guest
|
Posted: Wed Sep 01, 2004 10:10 am Post subject: Re: Overloading operator<< on std::pair<> |
|
|
Ivan Korotkov <korotkov2 (AT) ztel (DOT) ru> writes:
| Quote: | But ADL isn't the only thing happening here. It is the resolution of
depenendent names (also called two-phase lookup) which determines
that only ADL will be used to find cannidate functions for the
use(s) of operator<< inside the operator= template.
And what else can be used? Is there some info source I need to take a look
at?
|
My info source was sections 14.6 and 3.4 in the standard. However I
believe the Vandervoode and Josuttis C++ Templates book has a
more readable explanation.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Wed Sep 01, 2004 9:39 pm Post subject: Re: Overloading operator<< on std::pair<> |
|
|
John Potter wrote:
<snip>
| Quote: | Because ostream_iterator is in namespace std, the search for the
operator<< used in ostream_iterator::operator= starts in that
namespace. Many operator<< are found in that namespace terminating
the search. They hide your global operator.
|
The operator<< functions in namespace std don't hide the operator<< in
the global namespace. The latter isn't declared before the point of
definition of ostream_iterator so there is nothing to hide. Ordinary
name lookup (as opposed to ADL) will only find functions that are
declared before the calling function's definition (or its template's
definition).
--
Ben Hutchings
Any smoothly functioning technology is indistinguishable from a rigged demo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Thu Sep 02, 2004 12:05 pm Post subject: Re: Overloading operator<< on std::pair<> |
|
|
On 1 Sep 2004 17:39:27 -0400, Ben Hutchings
<ben-public-nospam (AT) decadentplace (DOT) org.uk> wrote:
| Quote: | John Potter wrote:
Because ostream_iterator is in namespace std, the search for the
operator<< used in ostream_iterator::operator= starts in that
namespace. Many operator<< are found in that namespace terminating
the search. They hide your global operator.
The operator<< functions in namespace std don't hide the operator<< in
the global namespace. The latter isn't declared before the point of
definition of ostream_iterator so there is nothing to hide. Ordinary
name lookup (as opposed to ADL) will only find functions that are
declared before the calling function's definition (or its template's
definition).
|
I think you may have something to say, but did not say it well.
Consider this which passes your complaint but not the compiler.
#include
#include <utility>
using namespace std;
ostream& operator<< (ostream& ostr, const pair
return (ostr << val.first << ' ' << val.second.c_str());
}
#include
int main() {
ostream_iterator<pair oi(cout);
*oi = pair<int, string>(1, "a");
}
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Sat Sep 04, 2004 10:53 am Post subject: Re: Overloading operator<< on std::pair<> |
|
|
John Potter wrote:
| Quote: | On 1 Sep 2004 17:39:27 -0400, Ben Hutchings
[email]ben-public-nospam (AT) decadentplace (DOT) org.uk[/email]> wrote:
John Potter wrote:
Because ostream_iterator is in namespace std, the search for the
operator<< used in ostream_iterator::operator= starts in that
namespace. Many operator<< are found in that namespace terminating
the search. They hide your global operator.
The operator<< functions in namespace std don't hide the operator<< in
the global namespace. The latter isn't declared before the point of
definition of ostream_iterator so there is nothing to hide. Ordinary
name lookup (as opposed to ADL) will only find functions that are
declared before the calling function's definition (or its template's
definition).
|
What I wrote here assumes a correct implementation of two-phase name
lookup, of course.
| Quote: | I think you may have something to say, but did not say it well.
|
Perhaps.
| Quote: | Consider this which passes your complaint but not the compiler.
#include
#include
using namespace std;
ostream& operator<< (ostream& ostr, const pair
return (ostr << val.first << ' ' << val.second.c_str());
}
#include
int main() {
ostream_iterator oi(cout);
*oi = pair<int, string>(1, "a");
}
|
The global operator<< may well be hidden here but that's different
from the problem with the original code.
I say "may well be" because you cannot be sure that
<utility> do not define std::ostream_iterator. It is a mistake to
expect *any* overloaded operator that will be invoked by the standard
library to be found by ordinary name lookup, regardless of whether it
is also overloaded in namespace std.
--
Ben Hutchings
Kids! Bringing about Armageddon can be dangerous. Do not attempt it in
your own home. - Terry Pratchett and Neil Gaiman, `Good Omens'
[ 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
|
|