Topic: Default type for second template parameter of std::pair


Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Thu, 1 Nov 2007 04:00:03 GMT
Raw View
On Wed, 31 Oct 2007, James Dennett wrote:

| Gabriel Dos Reis wrote:
| > On Wed, 24 Oct 2007, James Dennett wrote:
| >
| > | Alexei Alexandrov wrote:
| > | > Hyman Rosen wrote:
| > | >> Just do
| > | >>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
| > | >> Then you can say
| > | >>      tpair<std::vector::const_iterator>::t
| > | >>
| > | > Yes, I can do that. But why not have it in the standard library?
| > |
| > | Because changing the standard library has costs,
| >
| > In this specific case, what are the costs?
| >
| > [...]
| >
| > | > Simple, doesn't hurt anybody and convenient for many people perhaps...
| > |
| > | We don't add things to C++ because they may "perhaps" be
| > | convenient for some people,
| >
| > In fact, we have done that several times -- for some definition of
| > `some'.  And I don't think that is bad in itself.
|
| I should have added "just".  There has to be more
| justification that this.

We have done that too :-)

| > [...]
| >
| > | The cost includes (but is not limited to) updating the standard,
| > | updating books/tutorials/vendor documentation, updating all
| > | implementations that wish to conform, updating conformity test
| > | suites, and explaining the change to interested individuals.
| >
| > All of which are going to happen whether std::pair is made more
| > convenient or not.
|
| Maybe you misunderstand: these things will happen, yes, but
| each change increases the cost of each of them.

In this specific case, what are they?

| > So I suspect, if there is any compelling reason
| > not to default the second parameter, it has not been listed yet.
|
| Maybe not, but nonetheless, no compelling reason to *make*
| the change has been given, and so it's likely that the change
| won't be made.

Convenience of notation is a very compelling one -- it helps reduce
the noise/signal ratio.  That is part of why we default the Allocator
to allocator<T> in containers, instead of requiring everybody to say
vector<int, allocator<int>>.

When the element type is named T, then pair<T, T> does not seem
horrendous to write; but most T in real programs are not named T.

--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
       http://www.cs.tamu.edu/people/faculty/gdr
 Texas A&M University -- Department of Computer Science
 301, Bright Building -- College Station, TX 77843-3112

---
[ 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: nevin@eviloverlord.com ("Nevin :-] Liber")
Date: Thu, 1 Nov 2007 14:52:25 GMT
Raw View
In article <Pine.LNX.4.64.0710312118350.14870@gauss.cs.tamu.edu>,
 gdr@cs.tamu.edu (Gabriel Dos Reis) wrote:

> Convenience of notation is a very compelling one -- it helps reduce
> the noise/signal ratio.  That is part of why we default the Allocator
> to allocator<T> in containers, instead of requiring everybody to say
> vector<int, allocator<int>>.

Well sure, but we are defaulting the 99% case; most users don't know or
care about the allocator being used (since it is something used
internally by vector and not typically accessed outside of the vector).
Using the same example, we don't default the first parameter of vector.
If I look at my code base, vector<char> is more common than any other
type, yet it would be absurd to make that the default.

> When the element type is named T, then pair<T, T> does not seem
> horrendous to write; but most T in real programs are not named T.

And in most real programs, it is rare that both types in a pair are
identical.  Defaulting it actually makes the language (a little) harder
to use, because all the users have to learn what is defaulted where so
that they can, at a minimum, read code that uses it.  Not worth it for
this case.

--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  773 961-1620

---
[ 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: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Thu, 1 Nov 2007 11:34:34 CST
Raw View
On Nov 1, 3:52 pm, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
> In article <Pine.LNX.4.64.0710312118350.14...@gauss.cs.tamu.edu>,
>  g...@cs.tamu.edu (Gabriel Dos Reis) wrote:
> > When the element type is named T, then pair<T, T> does not seem
> > horrendous to write; but most T in real programs are not named T.
>
> And in most real programs, it is rare that both types in a pair are
> identical.  Defaulting it actually makes the language (a little) harder
> to use, because all the users have to learn what is defaulted where so
> that they can, at a minimum, read code that uses it.  Not worth it for
> this case.

I have to agree for this special case. I can't remember, when
I *explicitely* wrote a std::pair with both members of the same type,
most probably because I would either use a C array or boost::array
(next week: std::array) for these situations.

Just my personal 2 Euro cent from Bremen,

Daniel Kr   gler



---
[ 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: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Thu, 1 Nov 2007 21:33:27 GMT
Raw View
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--8323584-758798845-1193952620=:1902
Content-Type: TEXT/PLAIN; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Thu, 1 Nov 2007, Daniel Kr=C3=BCgler wrote:

| On Nov 1, 3:52 pm, ne...@eviloverlord.com ("Nevin :-] Liber") wrote:
| > In article <Pine.LNX.4.64.0710312118350.14...@gauss.cs.tamu.edu>,
| >  g...@cs.tamu.edu (Gabriel Dos Reis) wrote:
| > > When the element type is named T, then pair<T, T> does not seem
| > > horrendous to write; but most T in real programs are not named T.
| >
| > And in most real programs, it is rare that both types in a pair are
| > identical.  Defaulting it actually makes the language (a little) hard=
er
| > to use, because all the users have to learn what is defaulted where s=
o
| > that they can, at a minimum, read code that uses it.  Not worth it fo=
r
| > this case.
|=20
| I have to agree for this special case. I can't remember, when
| I *explicitely* wrote a std::pair with both members of the same type,
| most probably because I would either use a C array or boost::array
| (next week: std::array) for these situations.

So, I pesume you would propose to change the return type of
equal_range() and friends to std::array?=20

--=20
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
       http://www.cs.tamu.edu/people/faculty/gdr
 Texas A&M University -- Department of Computer Science
 301, Bright Building -- College Station, TX 77843-3112
--8323584-758798845-1193952620=:1902--

---
[ 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: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Thu, 1 Nov 2007 16:39:56 CST
Raw View
On Thu, 1 Nov 2007, Nevin :-] Liber wrote:

| In article <Pine.LNX.4.64.0710312118350.14870@gauss.cs.tamu.edu>,
|  gdr@cs.tamu.edu (Gabriel Dos Reis) wrote:
|
| > Convenience of notation is a very compelling one -- it helps reduce
| > the noise/signal ratio.  That is part of why we default the Allocator
| > to allocator<T> in containers, instead of requiring everybody to say
| > vector<int, allocator<int>>.
|
| Well sure, but we are defaulting the 99% case; most users don't know or
| care about the allocator being used (since it is something used
| internally by vector and not typically accessed outside of the vector).
| Using the same example, we don't default the first parameter of vector.

I'm not sure I follow the analogy here.

| If I look at my code base, vector<char> is more common than any other
| type, yet it would be absurd to make that the default.
|
| > When the element type is named T, then pair<T, T> does not seem
| > horrendous to write; but most T in real programs are not named T.
|
| And in most real programs, it is rare that both types in a pair are
| identical.

I suspect it depends on one's definition of `real programs'.
Maybe it's worth pointing out that there are algorithms in the
standard library with exactly that property, e.g. equal_range().


--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
       http://www.cs.tamu.edu/people/faculty/gdr
 Texas A&M University -- Department of Computer Science
 301, Bright Building -- College Station, TX 77843-3112

---
[ 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: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Fri, 2 Nov 2007 09:35:14 CST
Raw View
On Nov 1, 10:33 pm, g...@cs.tamu.edu (Gabriel Dos Reis) wrote:
> On Thu, 1 Nov 2007, Daniel Kr   gler wrote:
> | I have to agree for this special case. I can't remember, when
> | I *explicitely* wrote a std::pair with both members of the same type,
> | most probably because I would either use a C array or boost::array
> | (next week: std::array) for these situations.
>
> So, I pesume you would propose to change the return type of
> equal_range() and friends to std::array?

No, I did neither say so, nor did I meant that. My answer
has to be read literally in the sense of "I can't remember"
and combine this with "explicitely", you lose some of the
occasions, where I indirectly used that. E.g. I *know*, that
I used std::vector<int>, std::vector<some_use_full_type>
yesterday and the day before that. If you ask me *when*
I used e.g. equal_range, I can't remember (And to prevent
any further assumptions about my opinions or proposals:
This should *not* be understood that I think that this
algorithm is not useful). I also cannot remember, when
I used std::vector<some_use_full_type, some_also_useful_allocator>
the last time (which also does not mean that I think that
the allocator parameter is not useful).
One reason that I probably have rarely missed this
thinkable convenience for std::pair is due to my usual
approach, that I define a typedef at the point where I
probably use the same type more than once.

Just out of interest I checked both the current standard
and and of one of the recent drafts (I was too lazy to
download the newest one, so I took N2369) for occurrences
of std::pair and divided these into the cases "heterogen",
"homogen", and "potentially homogen". The last point
is one, where under given conditions the types can
reasonably be the same:

1) ISO 14882-2003:
Heterogen:
get_temporary_buffer
map, multi_map: insert

Homogen:
map, multi_map: equal_range
Algorithm: equal_range

Potentially homogen:
make_pair
Algorithm: mismatch

2) N2369:
Heterogen:
get_temporary_buffer
map, multi_map: insert, emplace

Homogen:
map, multi_map: equal_range
sub_match
Algorithm: equal_range, min_max, minmax_element

Potentially homogen:
make_pair
Algorithm: mismatch

We see that there is a tendency of more newer usages
with pair in homogenic context. On the other hand
the upcoming standard also provides more tools which
free us programmers from explicit type notations (e.g.
using auto in the new form).

To summarize: I really would not bother, if someone
provides a proposal to add a default parameter to
std::pair - but I hope that this would not have the effect
that IMO more important ones (just to name one:
variadic templates) would be skipped instead.

Greetings from Bremen,

Daniel Kr   gler


---
[ 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: Alexei Alexandrov <alexei.alexandrov@gmail.com>
Date: Tue, 23 Oct 2007 15:11:42 CST
Raw View
Hi All,

I wonder why std::pair doesn't default the second template parameter
to the first one? I've had quite a bit of cases where I need to
represent 2 values of the same type and this default would make my
code rather shorter. Say, for an iterator range:

std::pair<std::vector::const_iterator>

instead of

std::pair<std::vector::const_iterator, std::vector::const_iterator>

etc.

Is there any STL implementation which does it? Does Standard prohibit
to implementations to have deviations like this?

Thanks!

---
[ 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: Hyman Rosen <hyrosen@mail.com>
Date: Tue, 23 Oct 2007 16:19:06 CST
Raw View
Alexei Alexandrov wrote:
> I've had quite a bit of cases where I need to represent 2 values
 > of the same type and this default would make my code rather shorter.

Just do
     template <typename T> struct tpair { typedef std::pair<T, T> t; };
Then you can say
     tpair<std::vector::const_iterator>::t

---
[ 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: Alexei Alexandrov <alexei.alexandrov@gmail.com>
Date: Wed, 24 Oct 2007 13:28:01 CST
Raw View
Hyman Rosen wrote:
>
> Just do
>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
> Then you can say
>      tpair<std::vector::const_iterator>::t
>
Yes, I can do that. But why not have it in the standard library?
Simple, doesn't hurt anybody and convenient for many people perhaps...

---
[ 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: jdennett@acm.org (James Dennett)
Date: Wed, 24 Oct 2007 18:50:26 GMT
Raw View
Alexei Alexandrov wrote:
> Hyman Rosen wrote:
>> Just do
>>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
>> Then you can say
>>      tpair<std::vector::const_iterator>::t
>>
> Yes, I can do that. But why not have it in the standard library?

Because changing the standard library has costs, and in this
case the benefit of the change has not been demonstrated to
be significant.

> Simple, doesn't hurt anybody and convenient for many people perhaps...

We don't add things to C++ because they may "perhaps" be
convenient for some people, or C++ would have a 10,000
page standard rather than today's 1,000 page standard.

The cost includes (but is not limited to) updating the standard,
updating books/tutorials/vendor documentation, updating all
implementations that wish to conform, updating conformity test
suites, and explaining the change to interested individuals.

That's simply not going to happen when a simple C++09 template
using declaration will cover this use case.  I've rarely had to
explicitly name std::pair<T,T>, certainly not enough for me to
find a special case notation for it helpful.  It's possible that
others have different experience, but we've seen little evidence.
This isn't something I've seen requested before.

-- James

---
[ 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: Alexei Alexandrov <alexei.alexandrov@gmail.com>
Date: Thu, 25 Oct 2007 10:04:55 CST
Raw View
James Dennett wrote:
>
> Because changing the standard library has costs, and in this
> case the benefit of the change has not been demonstrated to
> be significant.
>
> ....

[sigh] understood...

Thanks for the detailed answer!

---
[ 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: Greg Herlihy <greghe@mac.com>
Date: Sat, 27 Oct 2007 06:17:00 CST
Raw View
On Oct 23, 3:19 pm, Hyman Rosen <hyro...@mail.com> wrote:
> Alexei Alexandrov wrote:
> > I've had quite a bit of cases where I need to represent 2 values
>
>  > of the same type and this default would make my code rather shorter.
>
> Just do
>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
> Then you can say
>      tpair<std::vector::const_iterator>::t

This solution requires a lot of "scaffolding" (whose purpose may not
be immediately evident). Furthermore, the name of the resulting
"alias" - falls far short of the ideal. Instead of being able to use
tpair<T> as an alias for std::pair<T, T>, the programmer must remember
to specify tpair<T>::t instead. And adding yet another scoped type to
an already overabundant supply of scoped types, will not make working
with the Standard Library's templates classes any easier - that much
is certain.

So a more elegant solution would map std::pair<T, T> to tpair<T> both
directly and succinctly:

    template <class T>
        using tpair = std::pair<T, T>;

Note that this solution relies on "template aliases" - a C++09
language feature that is probably not (yet) supported by current C++
compilers. So the practicality of this approach is open to question.
Nevertheless, when support for template aliases does arrive, it will
certainly make for a nice addition to the language.

Greg



---
[ 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: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Wed, 31 Oct 2007 09:48:11 CST
Raw View
On Wed, 24 Oct 2007, James Dennett wrote:

| Alexei Alexandrov wrote:
| > Hyman Rosen wrote:
| >> Just do
| >>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
| >> Then you can say
| >>      tpair<std::vector::const_iterator>::t
| >>
| > Yes, I can do that. But why not have it in the standard library?
|
| Because changing the standard library has costs,

In this specific case, what are the costs?

[...]

| > Simple, doesn't hurt anybody and convenient for many people perhaps...
|
| We don't add things to C++ because they may "perhaps" be
| convenient for some people,

In fact, we have done that several times -- for some definition of
`some'.  And I don't think that is bad in itself.

[...]

| The cost includes (but is not limited to) updating the standard,
| updating books/tutorials/vendor documentation, updating all
| implementations that wish to conform, updating conformity test
| suites, and explaining the change to interested individuals.

All of which are going to happen whether std::pair is made more
convenient or not.  So I suspect, if there is any compelling reason
not to default the second parameter, it has not been listed yet.

--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
       http://www.cs.tamu.edu/people/faculty/gdr
 Texas A&M University -- Department of Computer Science
 301, Bright Building -- College Station, TX 77843-3112

---
[ 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 Dennett <jdennett@acm.org>
Date: Wed, 31 Oct 2007 10:56:42 CST
Raw View
Gabriel Dos Reis wrote:
> On Wed, 24 Oct 2007, James Dennett wrote:
>
> | Alexei Alexandrov wrote:
> | > Hyman Rosen wrote:
> | >> Just do
> | >>      template <typename T> struct tpair { typedef std::pair<T, T> t; };
> | >> Then you can say
> | >>      tpair<std::vector::const_iterator>::t
> | >>
> | > Yes, I can do that. But why not have it in the standard library?
> |
> | Because changing the standard library has costs,
>
> In this specific case, what are the costs?
>
> [...]
>
> | > Simple, doesn't hurt anybody and convenient for many people perhaps...
> |
> | We don't add things to C++ because they may "perhaps" be
> | convenient for some people,
>
> In fact, we have done that several times -- for some definition of
> `some'.  And I don't think that is bad in itself.

I should have added "just".  There has to be more
justification that this.

> [...]
>
> | The cost includes (but is not limited to) updating the standard,
> | updating books/tutorials/vendor documentation, updating all
> | implementations that wish to conform, updating conformity test
> | suites, and explaining the change to interested individuals.
>
> All of which are going to happen whether std::pair is made more
> convenient or not.

Maybe you misunderstand: these things will happen, yes, but
each change increases the cost of each of them.

> So I suspect, if there is any compelling reason
> not to default the second parameter, it has not been listed yet.

Maybe not, but nonetheless, no compelling reason to *make*
the change has been given, and so it's likely that the change
won't be made.

-- James

---
[ 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: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Wed, 31 Oct 2007 12:00:32 CST
Raw View
On Tue, 23 Oct 2007, Hyman Rosen wrote:

| Alexei Alexandrov wrote:
| > I've had quite a bit of cases where I need to represent 2 values
| > of the same type and this default would make my code rather shorter.
|
| Just do
|     template <typename T> struct tpair { typedef std::pair<T, T> t; };

Is there a fundamental reason to make the workaround necessary?

--
Dr. Gabriel Dos Reis (gdr@cs.tamu.edu), Assistant Professor
       http://www.cs.tamu.edu/people/faculty/gdr
 Texas A&M University -- Department of Computer Science
 301, Bright Building -- College Station, TX 77843-3112

---
[ 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                      ]