Topic: T & vs T const & overloading


Author: pdimov@mmltd.net (Peter Dimov)
Date: Sat, 19 May 2001 18:49:05 GMT
Raw View
Andrei Iltchenko <iltchenko@yahoo.com> wrote in message news:<20010518110547.74671.qmail@web12504.mail.yahoo.com>...
> Peter Dimov <pdimov@MailAndNews.com> wrote in message:

[...]

> > [1]
> >
> > Template argument deduction is performed as-if an
>  argument of type
> > '__unique &' was passed to f<T>(T const &). Success,
> no implicit
>
> There's no mentioning of "an argument" except to mean
> "template argument deduction" in 14.5.5.2. The section
> fails to mention how "an argument" which is to be used
> for deduction is to be created (it being an l-value or
> an r-value may be crucial for the result of the
> deduction).

Yes. I tend to think of an 'rvalue' of a reference type as being an
'lvalue', but the section could have been clearer.

> In fact, I agree with the posters of the
> issue that it's not clear if "an agument" is to be
> created at all,

I think that the authors of the section had 14.8.2.1 in mind; you
can't have implicit conversions in 14.8.2.4.

> as the section may well be interpreted
> as indicating that the deduction shall proceed as per
> 14.8.2.4, which is used when you take the address of
> an overloaded function template or member function
> template and which does not require any arguments.

So, if I understand this interpretation correctly, 14.5.5.2 implies
that the following steps are performed:

(1)

template<class T> void f(T &);

void (*pf)(__unique const &) = &f; // success, T = __unique const

(2)

template<class U> void f(U const &);

void (*pf)(__unique2 &) = &f; // failure

This means that f<U>(U const &) is more specialized than f<T>(T &),
because "the transformed template is at least as specialized as the
other if, and only if, the deduction succeeds..."

> If
> you interpret it that way, then the function template
> "template<class T> void h(T const&)" becomes more
> specialized than "template<class T> void h(T&)"

Ok. This matches my analysis above.

> meaning that the function template specialization
> "void h<const int>(const int&)" is a better viable
> function than "void h<int>(const int&)".

Why? The specialization of the more specialized function template
should be the better viable function, shouldn't it?

> > [2]
> >
> > The types 'T &' and 'T const &' are tested for
>  whether one of
> > them describes a subset of the types described by
>  the other. In
> > this case, 'T const &' is more specialized than 'T
>  &' because
> > 'T &', for T = U const, describes all const
>  references, while
> > 'T const &' can never describe 'int &', for example.
> >
> > Therefore, f<T>(T const &) is more specialized.

[...]

> I see no hint in the Standard that would allow for
> such an interpretation.

This interpretation is, I believe, equivalent to the 14.8.2.4-based
one, expressed in a different way.

--
Peter Dimov
Multi Media Ltd.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Sun, 20 May 2001 12:38:02 GMT
Raw View
Peter Dimov <pdimov@mmltd.net> wrote in message
news:7dc3b1ea.0105190756.11da3749@posting.google.com...
> Andrei Iltchenko <iltchenko@yahoo.com> wrote in message
news:<20010518110547.74671.qmail@web12504.mail.yahoo.com>...
> > Peter Dimov <pdimov@MailAndNews.com> wrote in message:
>
> [...]
>
> > > [1]
> > >
> > > Template argument deduction is performed as-if an
> >  argument of type
> > > '__unique &' was passed to f<T>(T const &). Success,
> > no implicit
> >
> > There's no mentioning of "an argument" except to mean
> > "template argument deduction" in 14.5.5.2. The section
> > fails to mention how "an argument" which is to be used
> > for deduction is to be created (it being an l-value or
> > an r-value may be crucial for the result of the
> > deduction).
>
> Yes. I tend to think of an 'rvalue' of a reference type as being an
> 'lvalue', but the section could have been clearer.

I didn't mean that. I meant that when deducing template arguments for the
following function template
"template<class T> void h(T&)" the function argument (which has been
synthesized) being an 'r-value' or an 'l-value' may result in the candidate
function being not viable.


> > In fact, I agree with the posters of the
> > issue that it's not clear if "an agument" is to be
> > created at all,
>
> I think that the authors of the section had 14.8.2.1 in mind; you
> can't have implicit conversions in 14.8.2.4.

Could be. However, 14.5.5.2/4 requires an exact match for each
argument/parameter pair and 14.8.2.1 has a provision for cases when the the
type of deduced A is a base class of the type of A, which is clearly not an
exact match. Moreover, an implicit conversion is one of the following three:
1. Standard conversion sequence;
2. User-defined conversion sequence;
3. Ellipsis conversion sequnce.
Both 14.8.2.1 and 14.8.2.4 do not allow for [2.] and [3.]. So I think the
phrase "so the deduction does not rely on implicit-conversions" in
14.5.5.2/4 is misplaced.


> > as the section may well be interpreted
> > as indicating that the deduction shall proceed as per
> > 14.8.2.4, which is used when you take the address of
> > an overloaded function template or member function
> > template and which does not require any arguments.
>
> So, if I understand this interpretation correctly, 14.5.5.2 implies
> that the following steps are performed:
>
> (1)
>
> template<class T> void f(T &);
>
> void (*pf)(__unique const &) = &f; // success, T = __unique const
>
> (2)
>
> template<class U> void f(U const &);
>
> void (*pf)(__unique2 &) = &f; // failure
>
> This means that f<U>(U const &) is more specialized than f<T>(T &),
> because "the transformed template is at least as specialized as the
> other if, and only if, the deduction succeeds..."

Agree.


> > If you interpret it that way, then the function template
> > "template<class T> void h(T const&)" becomes more
> > specialized than "template<class T> void h(T&)"
>
> Ok. This matches my analysis above.
>
> > meaning that the function template specialization
> > "void h<const int>(const int&)" is a better viable
> > function than "void h<int>(const int&)".
>
> Why? The specialization of the more specialized function template
> should be the better viable function, shouldn't it?

I made a typo, what I had in mind and what I should've written is this:

If you interpret it that way, then the function template
"template<class T> void h(T const&)" becomes more
specialized than "template<class T> void h(T&)"
meaning that the function template specialization
"void h<int>(const int&)" is a better viable
function than "void h<const int>(const int&)".

Thanks for pointing that out!


> > > [2]
> > >
> > > The types 'T &' and 'T const &' are tested for
> >  whether one of
> > > them describes a subset of the types described by
> >  the other. In
> > > this case, 'T const &' is more specialized than 'T
> >  &' because
> > > 'T &', for T = U const, describes all const
> >  references, while
> > > 'T const &' can never describe 'int &', for example.
> > >
> > > Therefore, f<T>(T const &) is more specialized.
>
> [...]
>
> > I see no hint in the Standard that would allow for
> > such an interpretation.
>
> This interpretation is, I believe, equivalent to the 14.8.2.4-based
> one, expressed in a different way.

I agree, should've read your explanation more carefully.


Cheers,

Andrei Iltchenko.



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Andrei Iltchenko <iltchenko@yahoo.com>
Date: Fri, 18 May 2001 16:45:41 GMT
Raw View
Peter Dimov <pdimov@MailAndNews.com> wrote in message:

> Original Message From "Andrei Iltchenko"
<iltchenko@yahoo.com>
>> Peter Dimov <pdimov@MailAndNews.com> wrote in
message
>> news:3B0F73E9@MailAndNews.com...
>>
>>> template<class T> void h(T &);
>>> template<class T> void h(T const &);
>>>
>>> void m()
>>> {
>>>   int const j = 0;
>>>   h(j); // which h? why?
>> This one is interesting. After the argument
deduction succeeds,
>> there are
>
> Indeed, that's why I'm asking.
>
>> two candidate functions:
>> "void h<const int>(const int&)" and "void
h<int>(const int&)".
>> Both the candidate functions are viable, however,
given the way
>> that partial ordering of function templates is
specified in the
>> curren version of the standard, it is not clear
which of the two
>> is more specialized or if each of them is as
specialized as the
>> other.
>>
>> See the related active issue at:
>>
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214

> As I read 14.5.5.2, there are two interpretations:
Yeah, 14.5.5.2 can be interpreted in a few different
ways, as shown in the active issue.

> [1]
>
> Template argument deduction is performed as-if an
argument of type
> '__unique &' was passed to f<T>(T const &). Success,
no implicit

There's no mentioning of "an argument" except to mean
"template argument deduction" in 14.5.5.2. The section
fails to mention how "an argument" which is to be used
for deduction is to be created (it being an l-value or
an r-value may be crucial for the result of the
deduction). In fact, I agree with the posters of the
issue that it's not clear if "an agument" is to be
created at all, as the section may well be interpreted
as indicating that the deduction shall proceed as per
14.8.2.4, which is used when you take the address of
an overloaded function template or member function
template and which does not require any arguments. If
you interpret it that way, then the function template
"template<class T> void h(T const&)" becomes more
specialized than "template<class T> void h(T&)"
meaning that the function template specialization
"void h<const int>(const int&)" is a better viable
function than "void h<int>(const int&)".

> conversions. Then the 'reverse' deduction - an
argument of type
> '__unique const &' passed to f<T>(T&) - is
performed, and it also
> succeeds. Ambiguity.


> [2]
>
> The types 'T &' and 'T const &' are tested for
whether one of
> them describes a subset of the types described by
the other. In
> this case, 'T const &' is more specialized than 'T
&' because
> 'T &', for T = U const, describes all const
references, while
> 'T const &' can never describe 'int &', for example.
>
> Therefore, f<T>(T const &) is more specialized.
>
> This interpretation, however, produces exactly the
opposite result
> compared to the non-template case, where 'int &' is
'more
> specialized' than 'int const &'.

I see no hint in the Standard that would allow for
such an interpretation.


Sincerely,

Andrei Iltchenko.

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - buy the things you want at great prices
http://auctions.yahoo.com/

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Peter Dimov <pdimov@MailAndNews.com>
Date: Thu, 17 May 2001 19:55:24 GMT
Raw View
>===== Original Message From "Andrei Iltchenko" <iltchenko@yahoo.com> =====
>Peter Dimov <pdimov@MailAndNews.com> wrote in message
>news:3B0F73E9@MailAndNews.com...
>> A 'simple' question:
>>
>> template<class T> void h(T &);
>> template<class T> void h(T const &);
>>
>> void m()
>> {
>>   int const j = 0;
>>   h(j); // which h? why?
>
>This one is interesting. After the argument deduction succeeds, there are

Indeed, that's why I'm asking.

>two candidate functions:
>"void h<const int>(const int&)" and "void h<int>(const int&)". Both the
>candidate functions are viable, however, given the way that partial ordering
>of function templates is specified in the curren version of the standard, it
>is not clear which of the two is more specialized or if each of them is as
>specialized as the other.
>
>See the related active issue at:
>http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214
>
>"void h<int>(const int&);" Because of 14.8.3.

As I read 14.5.5.2, there are two interpretations:

[1]

Template argument deduction is performed as-if an argument of type '__unique
&' was passed to f<T>(T const &). Success, no implicit conversions. Then the
'reverse' deduction - an argument of type '__unique const &' passed to
f<T>(T&) - is performed, and it also succeeds. Ambiguity.

[2]

The types 'T &' and 'T const &' are tested for whether one of them describes
a
subset of the types described by the other. In this case, 'T const &' is
more
specialized than 'T &' because 'T &', for T = U const, describes all const
references, while 'T const &' can never describe 'int &', for example.

Therefore, f<T>(T const &) is more specialized.

This interpretation, however, produces exactly the opposite result compared
to
the non-template case, where 'int &' is 'more specialized' than 'int const
&'.

The point is interesting for a number of reasons.

First, interpretation [2] doesn't resolve the ambigutity between, for
example,

template<class F> void f(F &);
template<class R> void f(R (*) ());

void g()
{
  f(&g);
}

Second, [how dare I post an off-topic - unrelated to C++0x - article?
wait...]
if the original example is ambiguous, then we are left with no way to write
a
'forwarding' function that can take _any_ argument by reference. The
canonical
way to do this was the T &/T const & overloading.

Shouldn't 'template<class T> void f(T &)' be made to work for non-const
rvalues? In fact, isn't the compiler allowed to add a 'const' to make it
work?
(14.8.2.1/3, first bullet.)

--
Peter Dimov
Multi Media Ltd.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Peter Dimov <pdimov@MailAndNews.com>
Date: Wed, 16 May 2001 15:15:43 GMT
Raw View
A 'simple' question:

void f(int &);
void f(int const &);

void g()
{
  int i = 0;
  f(i);  // which f? why?
}

template<class T> void h(T &);
template<class T> void h(T const &);

void m()
{
  int i = 0;
  h(i); // which h? why?
  int const j = 0;
  h(j); // which h? why?
}

--
Peter Dimov
Multi Media Ltd.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@spamcop.net>
Date: Wed, 16 May 2001 19:57:29 GMT
Raw View

Peter Dimov wrote:

> void g()
> {
>   int i = 0;
>   f(i);  // which f? why?
> }

f(int &).  int is a better match for "int" than "const int" is.

>
> template<class T> void h(T &);
> template<class T> void h(T const &);
>
> void m()
> {
>   int i = 0;
>   h(i); // which h? why?
>   int const j = 0;
>   h(j); // which h? why?
> }
>

h(T&) in the first case.  Same reason as above.
h(const T&) for the second, because h(int&) isn't possible (no way to
convert const int to int&).

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Andrei Iltchenko" <iltchenko@yahoo.com>
Date: Wed, 16 May 2001 20:15:52 GMT
Raw View
Peter Dimov <pdimov@MailAndNews.com> wrote in message
news:3B0F73E9@MailAndNews.com...
> A 'simple' question:
>
> void f(int &);
> void f(int const &);
>
> void g()
> {
>   int i = 0;
>   f(i);  // which f? why?
"void f(int&);"  Because of 13.3.3.2/3 bullet 5.

> }
>
> template<class T> void h(T &);
> template<class T> void h(T const &);
>
> void m()
> {
>   int i = 0;
>   h(i); // which h? why?
"void h<int>(int&);" Because of 13.3.3.2/3 bullet 5 and 14.8.3.

>   int const j = 0;
>   h(j); // which h? why?

This one is interesting. After the argument deduction succeeds, there are
two candidate functions:
"void h<const int>(const int&)" and "void h<int>(const int&)". Both the
candidate functions are viable, however, given the way that partial ordering
of function templates is specified in the curren version of the standard, it
is not clear which of the two is more specialized or if each of them is as
specialized as the other.

See the related active issue at:
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214

"void h<int>(const int&);" Because of 14.8.3.
> }


Cheers,

Andrei Iltchenko.




---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: Wed, 16 May 2001 20:21:46 GMT
Raw View
Ron Natalie wrote:
>
> Peter Dimov wrote:
>
> > void g()
> > {
> >   int i = 0;
> >   f(i);  // which f? why?
> > }
>
> f(int &).  int is a better match for "int" than "const int" is.
>
> >
> > template<class T> void h(T &);
> > template<class T> void h(T const &);
> >
> > void m()
> > {
> >   int i = 0;
> >   h(i); // which h? why?
> >   int const j = 0;
> >   h(j); // which h? why?
> > }
> >
>
> h(T&) in the first case.  Same reason as above.
> h(const T&) for the second, because h(int&) isn't possible (no way to
> convert const int to int&).

One point is missing from your analysis: Which template is used
to generate h<>(int const&).

The compiler uses h<int>(int const&) (i.e. the second one), because
it is more specialized than h<int const>(int const&) (i.e. the first
one).

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@spamcop.net>
Date: Wed, 16 May 2001 20:21:36 GMT
Raw View

Ron Natalie wrote:
>
> > template<class T> void h(T &);
> > template<class T> void h(T const &);
> >
> > void m()
> > {
> >   int i = 0;
> >   h(i); // which h? why?
> >   int const j = 0;
> >   h(j); // which h? why?
> > }
> >
>
> h(T&) in the first case.  Same reason as above.
> h(const T&) for the second, because h(int&) isn't possible (no way to
> convert const int to int&).
>

Ick my own answer is wrong here.  The above is ambiguous for the
"int const" case.  Both the first where T="int const" and the
second where T="int" match that case.

---
[ 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.research.att.com/~austern/csc/faq.html                ]