Topic: Two Questions about R-value reference( N2118)


Author: pongba@gmail.com
Date: Fri, 1 Dec 2006 10:21:10 CST
Raw View
On Dec 1, 1:47 pm, "Peter Dimov" <pdi...@gmail.com> wrote:
> Yes, you are right, the current wording in N2118 14.8.2.1/3 does imply
> that the type P == T&& is deducible from A& with T == A&. This would
> make the partial specialization of remove_reference<T&&> match A&,
> something that we don't want. I'm not sure what is the best way of
> fixing it.

Now this seems to get a little interesting:-)

Now that I think of what you said in the other post:

"Right. Disregard my other post. N2118 14.8.2.1/3 works by discarding
the && off P and replacing A with A&. So if P is T&&, T is deduced as
A& and P becomes A& && == A&. But this doesn't mean that T&& can be
deduced from A&, so it seems that the remove_reference example is fine;
only one of the two specializations matches. "

It seems reasonably right. What I said just proved that the
remove_reference<int> example *is* fine.
The trick here is that, when deducing template arguments from a
function template call, all call parameters of reference type(that is,
l-value reference or r-value reference) should have their & or &&
notation stripped, the resulting P is used to be compared with A,
which, if the corresponding call argument is a l-value, should be
substituted with A&.
To sum up, I think the wording in N2118 is totally fine, it just needs
more clarification.

In particular, I propose the following wording(to complement the
existent):

14.8.2.1 - Deducing template arguments from a function call

-3- If P is a cv-qualified type, the top level cv-qualifiers of P's
type are ignored for type deduction.
If P is of reference type(l-value reference or r-value reference), the
type referred to by P is used for type deduction(i.e. substitute P with
the type it refers to). Moreover, if the *original* P is of r-value
reference type, and the corresponding call argument a l-value, then the
type A& is used in place of A for type deduction.

In addition, I suggest modify "14.3.1 - Template type arguments" as the
following:

Any attempt to create a type using a template parameter T is determined
by the rule specified in 7.1.3( typedef specifier) with T treated *as
if* it's a typedef name defined with the corresponding template
argument.

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Sat, 2 Dec 2006 10:53:16 CST
Raw View
pongba@gmail.com wrote:
> On Dec 1, 8:50 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> > Right. Disregard my other post. N2118 14.8.2.1/3 works by discarding
> > the && off P and replacing A with A&. So if P is T&&, T is deduced as
> > A& and P becomes A& && == A&. But this doesn't mean that T&& can be
> > deduced from A&, so it seems that the remove_reference example is fine;
> > only one of the two specializations matches.
>
> Did I just lift a rock only to drop it on my own feet? I think so :-)

You've raised a very good point (a nice rock, if you prefer). I'm still
not sure that the N2118 wording says what we want it to say. In
particular, I'm thinking of the following two examples:

// 1

void f( string && x );
template<class Ch> void g( basic_string<Ch> && x );

int main()
{
    string x;

    f( x ); // works
    g( x ); // deduction fails?
}

// 2

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

int main()
{
    X x;
    f( x ); // deduction fails?
}

I've asked about these on c++std-core and James Widman thinks that the
deduction would fail.

---
[ 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: pongba@gmail.com
Date: Sun, 3 Dec 2006 02:23:49 CST
Raw View
On Dec 3, 12:53 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> // 1
>
> void f( string && x );
> template<class Ch> void g( basic_string<Ch> && x );
>
> int main()
> {
>     string x;
>
>     f( x ); // works
>     g( x ); // deduction fails?
>
> }// 2

This one will fail for sure:-) Coz basic_string<Ch> && is *explicitly*
a r-value reference, and the template deduction cases where the
deduction rule has been intentionally loosen(base-class, more
cv-qualification...) doesn't include this case.
But wait...
Does this mean that deducing template arguments from P, where P is a
r-value reference, doesn't cause the && of P been stripped for the
purpose of deduction?
In this case, "basic_string<Ch> &&" will be compared  to "string&"(i.e.
basic_string<char>&), and the deduction will try to find some Ch that
makes "basic_string<Ch> &&" *identical* to "string&"? Since that can't
happen( 'cause every such Ch will make "basic_string<Ch>&&" a r-value
reference, while "string&" is still a l-value reference), and the
exception cases don't include this, deduction fails!
Is this the right(or reasonable?) interpretation?

> template<class T> void f( T const && t );
>
> int main()
> {
>     X x;
>     f( x ); // deduction fails?
>
> }
> I've asked about these on c++std-core and James Widman thinks that the
> deduction would fail.

I think allowing this example is harmless( since you can't steal
anything from t anyway).
In particular, I think this one should be OK; since N2118/7.1.3 says
"... while an attempt to create the type ``rvalue-reference to cv TD''
creates the type TD", we can here find a T, which is X&, that makes T
const&& identical to X&. (Note that the const-ness doesn't matter at
all, since a reference type is already 'const', which will consume the
"const" here).

To sum up, I'm thinking that the key to clarify certain things here is
to allow:

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

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

and

template<typename T>
class C;
template<typename T>
class C<T&>;
template<typename T>
class C<T&&>;

especially the latter one.

While the whole point of perfect forwarding is for one not to care
about the l-value/r-value-ness of the reference type, I think people do
want these two examples to work as their intuition tells them.

I think the steps needed here is to make T&& more specialized than T&,
thus rule out the T&& one in overload resolution, *even if* the
deduction for both one succeed.
In the above cases, or remove_reference if you will, N2118 states that
both the deduction for T&& and T& will succeed if A is a l-value
reference, but this won't necessarily lead to ambiguous, since we can
use the partial ordering rule to rule out the T&& case.
This leads me to the following:
Suppose we synthesize a unique type T(which must not be a reference
type), then deduce T&& from T& will always succeed, while being not the
case the other way around. This will make T& more specialized than T&&,
which will, in turn, make the T& one be chosen.

Does this sound reasonable? ( Note that this interpretation will
minimize the modification to N2118, actually, N2118 could be left as
is. The partial ordering rule needs a little clarification though)

P.S. It seems that when deducing template arguments and P is a r-value
reference, it totally doesn't matter whether we strip the && off P or
not.
For example,
template<typename T>
void f(T&&);

int i;
f(i); // comparing T&&(no stripping) to int& will yield "T as int&",
while comparing T(stripped) to int& will yield the exact same thing!

another one:

template<typename Ch>
void f( basic_string<Ch> &&);

std::string s;
f(s); // comparing basic_string<Ch>&& to string& will fail, while
comparing basic_string<Ch> to string& would, too!

I think this bizarre situation is due to the bizarre inherence of
r-value reference, which, in turn, is due to the special purpose w.r.t.
perfect forwarding.

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Sun, 3 Dec 2006 13:43:39 CST
Raw View
pongba@gmail.com wrote:
> On Dec 3, 12:53 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> > // 1
> >
> > void f( string && x );
> > template<class Ch> void g( basic_string<Ch> && x );
> >
> > int main()
> > {
> >     string x;
> >
> >     f( x ); // works
> >     g( x ); // deduction fails?
> >
> > }// 2
>
> This one will fail for sure:-) Coz basic_string<Ch> && is *explicitly*
> a r-value reference, and the template deduction cases where the
> deduction rule has been intentionally loosen(base-class, more
> cv-qualification...) doesn't include this case.
> But wait...
> Does this mean that deducing template arguments from P, where P is a
> r-value reference, doesn't cause the && of P been stripped for the
> purpose of deduction?

It is stripped. But basic_string<Ch> doesn't match string&.

[...]

> P.S. It seems that when deducing template arguments and P is a r-value
> reference, it totally doesn't matter whether we strip the && off P or
> not.
> For example,
> template<typename T>
> void f(T&&);
>
> int i;
> f(i); // comparing T&&(no stripping) to int& will yield "T as int&",

No, T&& adainst int& fails deduction.

> while comparing T(stripped) to int& will yield the exact same thing!

T against int& works and yields T == int&.

To match the original intent, the special case of replacing A with A&
needs to be constrained to only come into play when P is T&&. We can
extend T cv && to also deduce an lvalue reference (but I'm not sure
that we want to.)

---
[ 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: pongba@gmail.com
Date: Sun, 3 Dec 2006 22:57:12 CST
Raw View
On Dec 4, 3:43 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> No, T&& adainst int& fails deduction.

Why should this fail? According to the deduction rule, we can find a
type T that makes T&& identical to int&, the T we found is int&, and
the match exact.
Actually I'm thinking allowing both to work, and use the partial
ordering rule to select the right one, just in case you didn't notice,
here's my opinion( from the other post):

"I think the steps needed here is to make T& more specialized than T&&,
(there was a typo in my other post)
thus rule out the T&& one in overload resolution, *even if* the
deduction for both one succeed.
In the above cases, or remove_reference if you will, N2118 states that
both the deduction for T&& and T& will succeed if A is a l-value
reference, but this won't necessarily lead to ambiguous, since we can
use the partial ordering rule to rule out the T&& case.
This leads me to the following:
Suppose we synthesize a unique type T(which must not be a reference
type), then deduce T&& from T& will always succeed, while being not the
case the other way around. This will make T& more specialized than T&&,
which will, in turn, make the T& one be chosen. "

The reason I resort to this way is that we have to partial order f(T&)
and f(T&&) in one way or another, and the partial ordering of class
template partial specializations is defined in terms of that of
function template.

Without proper partial ordering, the f(T&) v.s. f(T&&) case couldn't be
resolved, 'cause each one is exact match for a l-value call argument.

> To match the original intent, the special case of replacing A with A&
> needs to be constrained to only come into play when P is T&&. We can
> extend T cv && to also deduce an lvalue reference (but I'm not sure
> that we want to.)

I totally agree on this. Consider:

template<typename T>
void f(T const&&);

f(i);
f(int());

If we allow "T const&&" to be deduced from a l-value, then for f(i),
the deduced call-parameter type would be int&( *non-const*), while
f(int()) would yield int const&&( *const*). That's plumb inconsistent.

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Mon, 4 Dec 2006 10:13:29 CST
Raw View
pongba@gmail.com wrote:
> On Dec 4, 3:43 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> > No, T&& adainst int& fails deduction.
>
> Why should this fail? According to the deduction rule, we can find a
> type T that makes T&& identical to int&, the T we found is int&, and
> the match exact.

Type deduction doesn't work that way; X && never matches Y & and vice
versa, the types need to have the same form for it to succeed. In
principle, when matching T & against int &, T == int& can also produce
the target type, but it's not tried. When matching T const againg int&,
T == int& produces the target type, but is not tried. At least that's
my understanding of it.

---
[ 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: Howard Hinnant <howard.hinnant@gmail.com>
Date: Wed, 29 Nov 2006 09:56:54 CST
Raw View
In article <1164707130.301323.251100@j72g2000cwa.googlegroups.com>,
 pongba@gmail.com wrote:

> "Joe Gottman" wrote:
> >    How about std::remove_reference?
> >
> > template <typename T> struct remove_reference
> > {
> >     typedef T type;
> > };
> >
> > template <typename T>
> > struct remove_reference<T &>
> > {
> >     typedef T type;
> > };
> >
> > template <typename T>
> > struct remove_reference<T &&>
> > {
> >     typedef T type;
> > };
>
> Great example! Since the partial ordering of class template partial
> specializations is defined in terms of that of function templates,
> there seems to be a problem.

Yes, I agree, excellent example.  It sent me scurrying back to the CWG
for expert advise on this one.  James Widman was kind enough to explain
things to me, and I'll try not to muddle his explanation too much.

remove_reference works as Joe shows because in transforming the partial
specialization into a function signature for the template type deduction
process we use:

template <typename T> void f(remove_reference<T&>);
template <typename T> void f(remove_reference<T&&>);

with an argument call like:

f(remove_reference<int&>());

I.e. there is no opportunity to apply 14.3.1p4 or 14.8.2.1p3.

(and fwiw, this behavior is consistent with current compiler prototypes)

-Howard

---
[ 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: Howard Hinnant <howard.hinnant@gmail.com>
Date: Wed, 29 Nov 2006 09:57:02 CST
Raw View
In article <1164687428.748487.130240@l12g2000cwl.googlegroups.com>,
 pongba@gmail.com wrote:

> However, I thinks the partial ordering rule should include the cases
> where T&& is involved, in one way or another, just like the way it did
> to T&/T const&.
> After all, the bias to neither side when choosing between f(T&) and
> f(T&&) is counter-intuitive to say the least.

This is quite analogous to our current situation with:

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

struct A {};

const A g();

int main()
{
    f(g());
}

ambiguous;

    f<A>(A)
    f<const A>(const A&)

Perhaps we do want to tackle ambiguities such as these.  But if so, I
see this as a separate issue from just the rvalue reference.  It needs
to be motivated on its own merits and look across all similar
ambiguities.

-Howard

---
[ 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: pongba@gmail.com
Date: Wed, 29 Nov 2006 10:02:59 CST
Raw View
Peter Dimov wrote:
> There is no problem with remove reference since a type can never be
> both T& and T&&. The original ambiguity exists because in the T&& case,
> T is deduced as int&, and because of the reference collapsing rule, T&&
> is also int&. int & && is not a type, and neither is int & &, they
> "normalize themselves" to int &.

I don't think so(but maybe I misunderstood your point, feel free to
correct me).
The reason this example is ill-formed is that template type deduction
of class templates is defined in terms of that of function templates.
When we write remove_reference<int&>, an attempt is made to deduce T
from comparing T&(the P) to int&(the A), which sure will succeed, but
then another attempt is made to deduce T from comparing T&&(the P) to
int&(the A), and this will succeed too, since N2118 said that when
deduce T for a function template like f(T&&), the call argument type is
A& instead of A, which clearly indicates a comparation between T&& and
A&(here A is the *actual* non-reference-type of the call argument).

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Wed, 29 Nov 2006 11:26:06 CST
Raw View
pongba@gmail.com wrote:
> Peter Dimov wrote:
> > There is no problem with remove reference since a type can never be
> > both T& and T&&. The original ambiguity exists because in the T&& case,
> > T is deduced as int&, and because of the reference collapsing rule, T&&
> > is also int&. int & && is not a type, and neither is int & &, they
> > "normalize themselves" to int &.
>
> I don't think so(but maybe I misunderstood your point, feel free to
> correct me).
> The reason this example is ill-formed is that template type deduction
> of class templates is defined in terms of that of function templates.
> When we write remove_reference<int&>, an attempt is made to deduce T
> from comparing T&(the P) to int&(the A), which sure will succeed, but
> then another attempt is made to deduce T from comparing T&&(the P) to
> int&(the A), and this will succeed too, since N2118 said that when
> deduce T for a function template like f(T&&), the call argument type is
> A& instead of A, which clearly indicates a comparation between T&& and
> A&(here A is the *actual* non-reference-type of the call argument).

If it worked this way, remove_reference<int> would match both
specializations, since both T& and T&& can be deduced from int in the
context of a function template taking T& and T&&. Intuitively, in this
case the deduction operates on the types, not on function arguments,
and must yield an exact match, without taking into account the special
T & && case that only applies to a limited subset of function calls.
Formally, I'm having trouble identifying the text that says so, though.

---
[ 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: pongba@gmail.com
Date: Thu, 30 Nov 2006 10:22:50 CST
Raw View
Peter Dimov wrote:
> If it worked this way, remove_reference<int> would match both
> specializations, since both T& and T&& can be deduced from int in the
> context of a function template taking T& and T&&. Intuitively, in this

Actually, the way template argument deduction works in cases of class
templates *is* a bit different from that of function templates.
For function templates, if P is of reference type, then the referenced
type is used instead of P for deduction, while for class templates, the
P, whether is a reference type or not, stays the same.
For example:

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

int i;
f(i);  // here, P is T and A is int; deduction successful, with P
deduced as int.

but

template<typename T>
class C;

template<typename T>
class C<T&>{};

C<int> c; // the deduction for C<T&> will never succeed, 'cause P is
T&(i.e. the exact type).

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Thu, 30 Nov 2006 18:50:27 CST
Raw View
pongba@gmail.com wrote:
> Peter Dimov wrote:
> > If it worked this way, remove_reference<int> would match both
> > specializations, since both T& and T&& can be deduced from int in the
> > context of a function template taking T& and T&&. Intuitively, in this
>
> Actually, the way template argument deduction works in cases of class
> templates *is* a bit different from that of function templates.
> For function templates, if P is of reference type, then the referenced
> type is used instead of P for deduction, while for class templates, the
> P, whether is a reference type or not, stays the same.

Right. Disregard my other post. N2118 14.8.2.1/3 works by discarding
the && off P and replacing A with A&. So if P is T&&, T is deduced as
A& and P becomes A& && == A&. But this doesn't mean that T&& can be
deduced from A&, so it seems that the remove_reference example is fine;
only one of the two specializations matches.

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Thu, 30 Nov 2006 23:47:39 CST
Raw View
pongba@gmail.com wrote:
> Peter Dimov wrote:
> > If it worked this way, remove_reference<int> would match both
> > specializations, since both T& and T&& can be deduced from int in the
> > context of a function template taking T& and T&&. Intuitively, in this
>
> Actually, the way template argument deduction works in cases of class
> templates *is* a bit different from that of function templates.
> For function templates, if P is of reference type, then the referenced
> type is used instead of P for deduction, while for class templates, the
> P, whether is a reference type or not, stays the same.

Yes, you are right, the current wording in N2118 14.8.2.1/3 does imply
that the type P == T&& is deducible from A& with T == A&. This would
make the partial specialization of remove_reference<T&&> match A&,
something that we don't want. I'm not sure what is the best way of
fixing it.

---
[ 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: pongba@gmail.com
Date: Fri, 1 Dec 2006 00:03:49 CST
Raw View
On Dec 1, 8:50 am, "Peter Dimov" <pdi...@gmail.com> wrote:
> Right. Disregard my other post. N2118 14.8.2.1/3 works by discarding
> the && off P and replacing A with A&. So if P is T&&, T is deduced as
> A& and P becomes A& && == A&. But this doesn't mean that T&& can be
> deduced from A&, so it seems that the remove_reference example is fine;
> only one of the two specializations matches.

Did I just lift a rock only to drop it on my own feet? I think so :-)

---
[ 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: howard.hinnant@gmail.com (Howard Hinnant)
Date: Mon, 27 Nov 2006 15:42:34 GMT
Raw View
In article <1164526625.677496.66940@l39g2000cwd.googlegroups.com>,
 pongba@gmail.com wrote:

> template<typename T>
> void f(T&&);
> template<typeanme T>
> void f(T&);
>
> int i;
> f(i);  // call which?
>
> Should the partial ordering rule explicitly deal with this situation?

The current language sees this as ambiguous between:

    f<int>(int&);
    f<int&>(int&);

I haven't run across motivation to disambiguate these.  Indeed the
current rules were specifically written such that the T&& signature
could handle the intentions of f(T&) (i.e. perfect forwarding).

If one does want to disambiguate these (treat lvalues and rvalues
differently) then tag dispatching could be used (just as an example):

template <class T>
void
f_imp(T&, std::true_type);

template <class T>
void
f_imp(T&&, std::false_type);

template<typename T>
inline
void
f(T&& t)
{
    return f_imp(std::forward<T>(t),
                 std::integral_constant<bool,
                      std::is_lvalue_reference<T>::value>());
}

However after "moving" the std::lib and large parts of tr1, I've yet to
run across a use case for the above code.  More commonly f(T&&) is
forwarding to a function where template argument deduction is not
applicable (either non-template code or the template parameter is
already elsewhere specified).  std::pair is a good example of this:

template <class T1, class T2>
struct pair
{
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;

    template <class U, class V> pair(U&& x, V&& y)
        : first(std::forward<U>(x)),
          second(std::forward<V>(y)) {}

..
};

Here you do want to treat lvalue and rvalue U's differently, but the
code for actually doing that is (potentially) in T1's overloaded
constructor set.  At the pair level one can use identical source code
for both lvalue and rvalue U's.  So there is no overloading pair(U&,V&).

-Howard

---
[ 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?Pedro_Lamar=E3o?=" <pedro.lamarao@gmail.com>
Date: Mon, 27 Nov 2006 09:49:12 CST
Raw View
On 26 nov, 21:59, pon...@gmail.com wrote:

> Another question, consider:
>
> template<typename T>
> void f(T&&);
> template<typeanme T>
> void f(T&);
>
> int i;
> f(i);  // call which?

i is an l-value, so it will be bound to the second overload.
Moving must be explicitly cast in this case:

  f(static_cast<int&&>(i));

or like this, if it makes it into de library:

  f(std::move(i));

--
 Pedro Lamar   o


---
[ 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: jgottman@carolina.rr.com ("Joe Gottman")
Date: Tue, 28 Nov 2006 05:11:37 GMT
Raw View
[Repost]
"Howard Hinnant" <howard.hinnant@gmail.com> wrote in message
news:howard.hinnant-E36D06.08522527112006@syrcnyrdrs-03-ge0.nyroc.rr.com...
> In article <1164526625.677496.66940@l39g2000cwd.googlegroups.com>,
> pongba@gmail.com wrote:
>
>> template<typename T>
>> void f(T&&);
>> template<typeanme T>
>> void f(T&);
>>
>> int i;
>> f(i);  // call which?
>>
>> Should the partial ordering rule explicitly deal with this situation?
>
> The current language sees this as ambiguous between:
>
>    f<int>(int&);
>    f<int&>(int&);
>
> I haven't run across motivation to disambiguate these.  Indeed the
> current rules were specifically written such that the T&& signature
> could handle the intentions of f(T&) (i.e. perfect forwarding).

   How about std::remove_reference?

template <typename T> struct remove_reference
{
    typedef T type;
};

template <typename T>
struct remove_reference<T &>
{
    typedef T type;
};

template <typename T>
struct remove_reference<T &&>
{
    typedef T type;
};


Joe Gottman

---
[ 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: pongba@gmail.com
Date: Mon, 27 Nov 2006 23:10:57 CST
Raw View
Howard Hinnant wrote:
> In article <1164526625.677496.66940@l39g2000cwd.googlegroups.com>,
>  pongba@gmail.com wrote:
>
> > template<typename T>
> > void f(T&&);
> > template<typeanme T>
> > void f(T&);
> >
> > int i;
> > f(i);  // call which?
> >
> > Should the partial ordering rule explicitly deal with this situation?
>
> The current language sees this as ambiguous between:
>
>     f<int>(int&);
>     f<int&>(int&);
>
It seems to me that the overload resolution should choose f(T&) since
it's obviously the intention.

> I haven't run across motivation to disambiguate these.  Indeed the
> current rules were specifically written such that the T&& signature
> could handle the intentions of f(T&) (i.e. perfect forwarding).
>
> If one does want to disambiguate these (treat lvalues and rvalues
> differently) then tag dispatching could be used (just as an example):
>

That's good observation:-)

> template <class T>
> void
> f_imp(T&, std::true_type);
>
> template <class T>
> void
> f_imp(T&&, std::false_type);
>
> template<typename T>
> inline
> void
> f(T&& t)
> {
>     return f_imp(std::forward<T>(t),
>                  std::integral_constant<bool,
>                       std::is_lvalue_reference<T>::value>());
> }

Again, good example.
However, I thinks the partial ordering rule should include the cases
where T&& is involved, in one way or another, just like the way it did
to T&/T const&.
After all, the bias to neither side when choosing between f(T&) and
f(T&&) is counter-intuitive to say the least.

---
[ 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: pongba@gmail.com
Date: Tue, 28 Nov 2006 09:42:33 CST
Raw View
"Joe Gottman" wrote:
>    How about std::remove_reference?
>
> template <typename T> struct remove_reference
> {
>     typedef T type;
> };
>
> template <typename T>
> struct remove_reference<T &>
> {
>     typedef T type;
> };
>
> template <typename T>
> struct remove_reference<T &&>
> {
>     typedef T type;
> };

Great example! Since the partial ordering of class template partial
specializations is defined in terms of that of function templates,
there seems to be a problem.

---
[ 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: "Peter Dimov" <pdimov@gmail.com>
Date: Tue, 28 Nov 2006 11:20:59 CST
Raw View
"Joe Gottman" wrote:
> [Repost]
> "Howard Hinnant" <howard.hinnant@gmail.com> wrote in message
> news:howard.hinnant-E36D06.08522527112006@syrcnyrdrs-03-ge0.nyroc.rr.com...
> > In article <1164526625.677496.66940@l39g2000cwd.googlegroups.com>,
> > pongba@gmail.com wrote:
> >
> >> template<typename T>
> >> void f(T&&);
> >> template<typeanme T>
> >> void f(T&);
> >>
> >> int i;
> >> f(i);  // call which?
> >>
> >> Should the partial ordering rule explicitly deal with this situation?
> >
> > The current language sees this as ambiguous between:
> >
> >    f<int>(int&);
> >    f<int&>(int&);
> >
> > I haven't run across motivation to disambiguate these.  Indeed the
> > current rules were specifically written such that the T&& signature
> > could handle the intentions of f(T&) (i.e. perfect forwarding).
>
>    How about std::remove_reference?
>
> template <typename T> struct remove_reference
> {
>     typedef T type;
> };
>
> template <typename T>
> struct remove_reference<T &>
> {
>     typedef T type;
> };
>
> template <typename T>
> struct remove_reference<T &&>
> {
>     typedef T type;
> };

There is no problem with remove reference since a type can never be
both T& and T&&. The original ambiguity exists because in the T&& case,
T is deduced as int&, and because of the reference collapsing rule, T&&
is also int&. int & && is not a type, and neither is int & &, they
"normalize themselves" 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.comeaucomputing.com/csc/faq.html                      ]





Author: pongba@gmail.com
Date: Sun, 26 Nov 2006 17:59:44 CST
Raw View
A careful reading of N2118 revealed that the modification of 7.1.3(i.e.
the typedef specifier) and that of 14.3.1(i.e. template type arguments)
essentially articulated the same rule, which, if stated simply, is "the
attempt to create a lvalue-reference(whether cv qualified or not) to
some reference-type RT(RT shall be a typedef-name or template type
parameter) essentially modifys the reference part of the type RT into
lvalue-reference and keeping other aspects intact; while the attempt to
create a rvalue-reference(whether cv qualified or not) to such RT
leaves RT as is. So, should the rule for 14.3.1 be defined in terms of
that of 7.1.3, or just refer to that of 7.1.3?

P.S. Should the above wording be added as a note in order to clarify
this special-made rule? ( coz I think the asymmetric-ness of the rules
for l-value reference and r-value reference will probably confuse the
novices.)
Also, it'd be the best if this wording include a little motivation
description of the rule, which of course is for perfect forwarding,
that'll use several lines of words but will worth a lot:)

Another question, consider:

template<typename T>
void f(T&&);
template<typeanme T>
void f(T&);

int i;
f(i);  // call which?

Should the partial ordering rule explicitly deal with this situation?

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