Topic: std::pair istream >> operator


Author: Martin <wpcmame@hotmail.com>
Date: Wed, 28 Nov 2007 11:55:57 CST
Raw View
> The solution I'd always seen (in pre-standard complex) was to
> apply (width()-3)/2 to each of the components of the complex.

The draft standard says about stream::operator<<

Effects: inserts the complex number x onto the stream o as if it were
implemented as follows:
template<class T, class charT, class traits>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& o, const complex<T>& x)
{
basic_ostringstream<charT, traits> s;
s.flags(o.flags());
s.imbue(o.getloc());
s.precision(o.precision());
s << '(' << x.real() << "," << x.imag() << ')';
return o << s.str();
}

>
> > If I could put in a recommendation it would be:
> > - Add a separator field to the ios_base structure (default =
> > traits::eof() -> ctype.isspace for input and space for output)
> > - Add manipulators: separator, setseparator, showseparator,
> > noshowseparator (default)
> > - Width, fill etc applies to each item (but not the separator)
> > - separator is also used to end stream input for string.
>
> None of which addresses the basic problem of outputting
> std::pair (or boost::tuple): the fact that the type may have
> different semantic signification at different places in the
> program.

Isn't that something that applies to all types?

Built in types like double got modifers on format, precision etc. If
you need some non-standard formatting you implement your own but it
still nice to have a default.

> Although there may be some special cases, my own feeling is that
> any use of std::pair (and probably most uses of boost::tuple)
> are simply poor programming.

I agree but admit I'm using them a lot. Specially in containers.

To make your own "named_tuple" you need to implement the operators as
well. I have some macros to do it but it quickly get inconvenient.

If I temporary need a set or map with 2 values inside a funtion I just
do a single line

typedef std::map<int, std::pair<std::string, int> > mymap;

To do it with a macro you first need to create the type outside the
function (template types need external linkage) which could be in .h
file somewhere.

NAMED_TUPLE(mytuple, std::string, name, int, value);
.

typedef std::map<int, mytuple> mymap;

It would be nice with a feature like the anonymous types in C# 3.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Thu, 29 Nov 2007 11:07:50 CST
Raw View
On Nov 28, 6:55 pm, Martin <wpcm...@hotmail.com> wrote:
> > The solution I'd always seen (in pre-standard complex) was to
> > apply (width()-3)/2 to each of the components of the complex.

> The draft standard says about stream::operator<<

> Effects: inserts the complex number x onto the stream o as if it were
> implemented as follows:
> template<class T, class charT, class traits>
> basic_ostream<charT, traits>&
> operator<<(basic_ostream<charT, traits>& o, const complex<T>& x)
> {
> basic_ostringstream<charT, traits> s;
> s.flags(o.flags());
> s.imbue(o.getloc());
> s.precision(o.precision());
> s << '(' << x.real() << "," << x.imag() << ')';
> return o << s.str();
> }

That's not the draft; that's the current state.  And there's a
DR because of it, I think; it's obviously broken.  (You can't
even use it in most locales; it would result in something like
(1,0,2,0) in the French locale, for example.)

> > > If I could put in a recommendation it would be:
> > > - Add a separator field to the ios_base structure (default =
> > > traits::eof() -> ctype.isspace for input and space for output)
> > > - Add manipulators: separator, setseparator, showseparator,
> > > noshowseparator (default)
> > > - Width, fill etc applies to each item (but not the separator)
> > > - separator is also used to end stream input for string.

> > None of which addresses the basic problem of outputting
> > std::pair (or boost::tuple): the fact that the type may have
> > different semantic signification at different places in the
> > program.

> Isn't that something that applies to all types?

Not to the same degree.

> Built in types like double got modifers on format, precision
> etc. If you need some non-standard formatting you implement
> your own but it still nice to have a default.

The problem is that, unlike double, there is no reasonable
default.

> > Although there may be some special cases, my own feeling is that
> > any use of std::pair (and probably most uses of boost::tuple)
> > are simply poor programming.

> I agree but admit I'm using them a lot. Specially in containers.

> To make your own "named_tuple" you need to implement the
> operators as well.  I have some macros to do it but it quickly
> get inconvenient.

> If I temporary need a set or map with 2 values inside a
> funtion I just do a single line

> typedef std::map<int, std::pair<std::string, int> > mymap;

This is fine for quick hacking, but it's not something that
would make its way into production code.  The fact that those
two values are associated has some application specific
signification, and their names in the association aren't first
and second.

Consider something like the return value of map<>::insert.  Does
the name "first" tell me in any way whether I'm dealing with the
iterator or the indication as to whether the insertion changed
something or not?  (Admittedly, that's an extreme case: but even
in the case of ranges, wouldn't names like top, or upper be more
appropriate.)

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 20 Nov 2007 17:27:36 CST
Raw View
On Nov 19, 8:08 pm, tazmas...@rocketmail.com ("Jim Langston") wrote:
> "Andrey" <andrey_rya...@bk.ru> wrote in message

> news:a7eb92bf-1ab8-438d-8bca-b6f7cfcc056c@o6g2000hsd.googlegroups.com...

> > I'm wondering why there is no standard operator defined like
> > the following?

> > template<typename First, typename Second>
> > istream & operator >> (istream & in, pair<First, Second> & p) {
> > return in>>p.first>>p.second;
> > }

> > I always define it by hand.

> Consider, also, that your implemnation can be broken for
> std::pair<std::string, int> since the std::string can contain a space.  In
> which case it might need to be
> std::getline( in, p.first );
> return in >> p.second;

> or even with <int, std::string> you probably want a
> std::getline for the second parameter.

That's a problem with std::string in general.  I use a special
class, ParsableString, when I have to do round trip IO on a
string, and no other solution is readily available.

The problem is that you need a separator, even with
std::pair<int,int>.  And that separator will probably depend on
what the std::pair is being used for.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 20 Nov 2007 17:27:11 CST
Raw View
On Nov 19, 7:19 pm, "Jim Langston" <tazmas...@rocketmail.com> wrote:
> "Andrey" <andrey_rya...@bk.ru> wrote in message

> news:a7eb92bf-1ab8-438d-8bca-b6f7cfcc056c@o6g2000hsd.googlegroups.com...

> > I'm wondering why there is no standard operator defined like
> > the following?

> > template<typename First, typename Second>
> > istream & operator >> (istream & in, pair<First, Second> & p) {
> > return in>>p.first>>p.second;
> > }

> > I always define it by hand.

> Probably the same reason operator( istream& in, std::vector& p ) is not
> defined.  Or map.  Or list.  Or any of the other containers.  They are
> trivial to define

Are they?  Write a definition of std::pair<double,double> that
will work when invoked by the std::ostream_iterator of the type?

Perhaps the biggest argument for defining them in the standard
is that for built-in types, they must be defined in std::, which
is something a user isn't allowed to do.

Of course, the argument only holds water if you believe that
they should be overloaded.  Given that the types in question
have no semantics, and no real "standard" format, there should
probably never be an << or a >> for such types in a program,
neither in the standard nor in user code.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 20 Nov 2007 17:26:45 CST
Raw View
On Nov 19, 7:18 pm, jcof...@taeus.com (Jerry Coffin) wrote:
> In article <84eb137f-aa46-443e-8f6a-
> 912487da7...@p69g2000hsa.googlegroups.com>, andrey_rya...@bk.ru says...

> [ ... ]

> > template <class First, class Second>
> > istream & operator >> (istream & in, pair<First, Second> & p) {
> >    return in>>p.first>>p.second;
> > }

> > In my opinion this is the only possible implementation as it is for
> > operators  '<' and '=='.

> IMO, this is wrong. The members of a pair are frequently delimited by
> something other than white space, in which case that delimiter has to be
> taken into account. For example, if you write a map out to a stream, you
> frequently use something like a colon to separate the items, in which
> case you have to ignore that colon when you read the data back in.

> You can/could accomplish that with a ctype facet that treats your chosen
> delimiter as white space, but that's a rather heavyweight solution,
> especially if only part of what you're reading from the stream is pairs.

There's actually been some discussion in this regard concerning
complex---the current specification of << and >> for complex
mean that it doesn't work in most European locales (where the
decimal is a comma, and a semi-colon is used to separate the
real and the imaginary parts).

It's a general problem.  In the case of std::pair, it is
compounded by the absense of any underlying semantics: the colon
is often appropriate when the pair is an element of a map, but
in many other cases, American use would be a comma, and European
a semicolon.  And in other cases (e.g. the pair is a range),
perhaps a hyphen or an elipsis would be more appropriate.

Overloading << and >> for types that are pure data structures,
without any real semantics (and this includes the standard
containers, as well as std::pair and the upcoming tuple) is
probably not a good idea.  Either in the standard, or in user
code.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Andrey <andrey_ryabov@bk.ru>
Date: Wed, 21 Nov 2007 11:54:17 CST
Raw View
All you have said definitely make sense!

But the boost::tuple has these operators defined (in
subnamespace ::tuples), look at this:
http://www.boost.org/libs/tuple/doc/tuple_users_guide.html#streaming
so the question become: Why does BGL use std::pair instead of
boost::tuple?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Sebastian Redl <e0226430@student.tuwien.ac.at>
Date: Mon, 26 Nov 2007 11:38:11 CST
Raw View
Andrey wrote:

> so the question become: Why does BGL use std::pair instead of
> boost::tuple?

Because the BGL is older than Boost.Tuples.

--
Sebastian Redl

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Martin <wpcmame@hotmail.com>
Date: Mon, 26 Nov 2007 11:42:13 CST
Raw View
On 21 Nov, 18:54, Andrey <andrey_rya...@bk.ru> wrote:
> But the boost::tuple has these operators defined (in
> subnamespace ::tuples), look at this:http://www.boost.org/libs/tuple/doc/tuple_users_guide.html#streaming
> so the question become: Why does BGL use std::pair instead of
> boost::tuple?

Just because it is implemented doesn't mean it is a good thing.

Tuple streaming use manipulators to set the separator which means that
you need access to the stream to use them (i.e. no lexical_cast etc)

On the other hand I don't think it is possible to put the separator in
a locale in a good way.
To follow the standard you need to add the separator to e.g. ctype (or
a new facet) and then have the facets sequence_put and sequence_get.

The problem is that you can't implement do_put & do_get for sequences
since it would result in virtual template functions.
i.e.
template <typename It>
virtual sequence_put::do_put(OutIt outit, ios_base& iosbase, It begin,
It end) {
  for (; begin!=end; ++begin)
    ...
}

which of course isn't possible.

Then you have the problem with the width stream manipulator. Don't
know how the tuple streaming handles it but I do know that complex got
it all wrong.
For complex the width is applied to the result string and not the
items.
cout << width(5) << complex(1,2)
becomes
"1,2  "
which makes it impossible to line up the items.
If the width is applied to each item you can always use an
intermediate string stream to limit the width of the result string.

If I could put in a recommendation it would be:
- Add a separator field to the ios_base structure (default =
traits::eof() -> ctype.isspace for input and space for output)
- Add manipulators: separator, setseparator, showseparator,
noshowseparator (default)
- Width, fill etc applies to each item (but not the separator)
- separator is also used to end stream input for string.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Tue, 27 Nov 2007 10:46:10 CST
Raw View
On Nov 26, 6:42 pm, Martin <wpcm...@hotmail.com> wrote:
> On 21 Nov, 18:54, Andrey <andrey_rya...@bk.ru> wrote:

    [...]
> Then you have the problem with the width stream manipulator.
> Don't know how the tuple streaming handles it but I do know
> that complex got it all wrong.  For complex the width is
> applied to the result string and not the items.
> cout << width(5) << complex(1,2)
> becomes
> "1,2  "
> which makes it impossible to line up the items.  If the width
> is applied to each item you can always use an intermediate
> string stream to limit the width of the result string.

The solution I'd always seen (in pre-standard complex) was to
apply (width()-3)/2 to each of the components of the complex.

> If I could put in a recommendation it would be:
> - Add a separator field to the ios_base structure (default =
> traits::eof() -> ctype.isspace for input and space for output)
> - Add manipulators: separator, setseparator, showseparator,
> noshowseparator (default)
> - Width, fill etc applies to each item (but not the separator)
> - separator is also used to end stream input for string.

None of which addresses the basic problem of outputting
std::pair (or boost::tuple): the fact that the type may have
different semantic signification at different places in the
program.  A format which would be appropriate for e.g. an
element in a map would certainly not be appropriate in other
cases, even if the types are identical.

Although there may be some special cases, my own feeling is that
any use of std::pair (and probably most uses of boost::tuple)
are simply poor programming.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Andrey <andrey_ryabov@bk.ru>
Date: Fri, 16 Nov 2007 11:24:16 CST
Raw View
Hello.
I'm wondering why there is no standard operator defined like the
following?

template<typename First, typename Second>
istream & operator >> (istream & in, pair<First, Second> & p) {
 return in>>p.first>>p.second;
}

I always define it by hand.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Sat, 17 Nov 2007 09:55:09 CST
Raw View
On Nov 16, 6:24 pm, Andrey <andrey_rya...@bk.ru> wrote:

> I'm wondering why there is no standard operator defined like the
> following?

> template<typename First, typename Second>
> istream & operator >> (istream & in, pair<First, Second> & p) {
>         return in>>p.first>>p.second;
> }

And how would you define it?  To do what?

> I always define it by hand.

I never use std::pair to begin with, so the problem doesn't come
up.  If I did, I would also define it by hand.  But I see no
reason to suppose that the definition would always be the same.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Andrey <andrey_ryabov@bk.ru>
Date: Sat, 17 Nov 2007 18:30:49 CST
Raw View
> And how would you define it?  To do what?


As std::pair provided to treat two values as a single unit there can
be only one posible  implementation of  this operator described below.

std::pair class is widely used in BGL (boost/graph libray).
The question arouse due to using this library. I wanted to use an
algorithm implemented with  BGL by a friend of mine using. His library
had this operator defined, as well as my program had. That made me
think that it was quite strange that there had not beed such operator
defined in std namespace.

-------------------------------------------------------
#include <iostream>

namespace my_ns {

template <class First, class Second>
std::istream & operator >> (std::istream & in, std::pair<First,
Second> & p) {
/* debug */ std::cout<<"my_ns::operator >> ";
 return in>>p.first>>p.second;
}

}

namespace his_ns {

template <class First, class Second>
std::istream & operator >> (std::istream & in, std::pair<First,
Second> & p) {
/* debug */ std::cout<<"his_ns::operator >> ";
 return in>>p.first>>p.second;
}
}


int main() {
 using namespace std;
 pair<int, float> p;

 using namespace my_ns;

 cin>>p;

 using namespace his_ns;

 his_ns::operator >> (cin, p);

 cout<<p.first<<endl<<p.second<<endl;

 return 0;
}
-----------------------------------------------------------------


>
> > I always define it by hand.
>
> I never use std::pair to begin with, so the problem doesn't come
> up.  If I did, I would also define it by hand.  But I see no
> reason to suppose that the definition would always be the same.
>
It's worth discussing.
I was wondering how would you changed the following implementation?

template <class First, class Second>
istream & operator >> (istream & in, pair<First, Second> & p) {
 return in>>p.first>>p.second;
}

In my opinion this is the only possible implementation as it is for
operators  '<' and '=='.




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Jim Langston" <tazmaster@rocketmail.com>
Date: Mon, 19 Nov 2007 12:19:02 CST
Raw View
"Andrey" <andrey_ryabov@bk.ru> wrote in message
news:a7eb92bf-1ab8-438d-8bca-b6f7cfcc056c@o6g2000hsd.googlegroups.com...
> Hello.
> I'm wondering why there is no standard operator defined like the
> following?
>
> template<typename First, typename Second>
> istream & operator >> (istream & in, pair<First, Second> & p) {
> return in>>p.first>>p.second;
> }
>
> I always define it by hand.

Probably the same reason operator( istream& in, std::vector& p ) is not
defined.  Or map.  Or list.  Or any of the other containers.  They are
trivial to define and some people may wish to do them differently.  Such as
maybe
return in >> p.second >> p.first;
or whatever.

If something is trivial to implement I don't see why it would need to be in
the standard.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: Mon, 19 Nov 2007 18:18:33 GMT
Raw View
In article <84eb137f-aa46-443e-8f6a-
912487da73ad@p69g2000hsa.googlegroups.com>, andrey_ryabov@bk.ru says...

[ ... ]

> template <class First, class Second>
> istream & operator >> (istream & in, pair<First, Second> & p) {
>  return in>>p.first>>p.second;
> }
>
> In my opinion this is the only possible implementation as it is for
> operators  '<' and '=='.

IMO, this is wrong. The members of a pair are frequently delimited by
something other than white space, in which case that delimiter has to be
taken into account. For example, if you write a map out to a stream, you
frequently use something like a colon to separate the items, in which
case you have to ignore that colon when you read the data back in.

You can/could accomplish that with a ctype facet that treats your chosen
delimiter as white space, but that's a rather heavyweight solution,
especially if only part of what you're reading from the stream is pairs.

--
    Later,
    Jerry.

The universe is a figment of its own imagination.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Mon, 19 Nov 2007 12:19:30 CST
Raw View
On Nov 18, 1:30 am, Andrey <andrey_rya...@bk.ru> wrote:
> > And how would you define it?  To do what?

> As std::pair provided to treat two values as a single unit
> there can be only one posible implementation of this
> operator described below.

How's that?  You mean that you'd always want "(first,second)"?
Or was that "(first;second)" (since the comma is the decimal
point in a lot of local).  Or maybe rather "[first;second]"?

Even when the semantics is clear (e.g. std::complex), it's not
always clear what the representation should be.

> std::pair class is widely used in BGL (boost/graph libray).
> The question arouse due to using this library. I wanted to use an
> algorithm implemented with  BGL by a friend of mine using. His library
> had this operator defined, as well as my program had.

That's exactly the risk.  You end up with two different
definitions.  In no case do you want this operator defined.

> That made me think that it was quite strange that there had
> not beed such operator defined in std namespace.

> -------------------------------------------------------
> #include <iostream>

> namespace my_ns {

> template <class First, class Second>
> std::istream & operator >> (std::istream & in, std::pair<First,
> Second> & p) {
> /* debug */     std::cout<<"my_ns::operator >> ";
>         return in>>p.first>>p.second;
> }
> }

> namespace his_ns {

> template <class First, class Second>
> std::istream & operator >> (std::istream & in, std::pair<First,
> Second> & p) {
> /* debug */     std::cout<<"his_ns::operator >> ";
>         return in>>p.first>>p.second;
> }
> }

Note that neither of these operators will be found if you're
using something like std::ostream_iterator with an std::pair of
basic types.

I'd also be interested in seeing the operator<<.
"out << p.first << p.second" obviously isn't acceptable.

> -----------------------------------------------------------------

> > > I always define it by hand.

> > I never use std::pair to begin with, so the problem doesn't come
> > up.  If I did, I would also define it by hand.  But I see no
> > reason to suppose that the definition would always be the same.

> It's worth discussing.
> I was wondering how would you changed the following implementation?

> template <class First, class Second>
> istream & operator >> (istream & in, pair<First, Second> & p) {
>         return in>>p.first>>p.second;
> }

As I said, I haven't yet found a reasonable use for std::pair.
(I know it's used in std::map, but that use is a good example of
a case where it's use is poor design: the semantics of the two
fields is NOT first and second, but key and value, and they
should be thus named.)  I do overload >> and << for the structs
or classes I use instead of std::pair.  But I rarely overload it
the same way: if the "pair" represents a range (often the case,
e.g. as in the return value of binary_search), then something
like:
    out << '[' << p.first << ';' << p.second << '[' ;
is what I would use here, or
    out << '[' << p.first << ',' << p.second << ')' ;
if the output were in English.  (How to represent a half-open
interval is locale dependent.  And intervals are one case where
std::pair might be acceptable... but you'd still have to tell
the << operator somehow whether the bound was open or closed,
for each bound.)

> In my opinion this is the only possible implementation as it
> is for operators  '<' and '=='.

Try it for output?  Does this implementation really do anything
reasonable, e.g. for std::pair<double,double>?

The real problem, of course, is that std::pair doesn't implement
anything, nor even imply any semantics.  So first, it's not
generally a good solution for much (because you want the
semantics apparent in the source code), and secondly, what it
should do for << and >> depend very much on the semantics.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: tazmaster@rocketmail.com ("Jim Langston")
Date: Mon, 19 Nov 2007 19:08:53 GMT
Raw View
"Andrey" <andrey_ryabov@bk.ru> wrote in message
news:a7eb92bf-1ab8-438d-8bca-b6f7cfcc056c@o6g2000hsd.googlegroups.com...
> Hello.
> I'm wondering why there is no standard operator defined like the
> following?
>
> template<typename First, typename Second>
> istream & operator >> (istream & in, pair<First, Second> & p) {
> return in>>p.first>>p.second;
> }
>
> I always define it by hand.

Consider, also, that your implemnation can be broken for
std::pair<std::string, int> since the std::string can contain a space.  In
which case it might need to be
std::getline( in, p.first );
return in >> p.second;

or even with <int, std::string> you probably want a std::getline for the
second parameter.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]