Topic: Initialization by conversion function


Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Fri, 28 Aug 2009 17:19:09 CST
Raw View
N2914 - 8.5.3/5 states:

"A reference to type =93cv1 T1=94 is initialized by an expression of type
=93cv2 T2=94 as follows:
- If the reference is an lvalue reference and the initializer
expression
-- is an lvalue (but is not a bit-field), and =93cv1 T1=94 is reference-
compatible with =93cv2 T2,=94 or
-- has a class type (i.e., T2 is a class type), where T1 is not
reference-related to T2, and can be implicitly converted to an lvalue
of type =93cv3 T3,=94 where =93cv1 T1=94 is reference-compatible with =93cv=
3
T3=94 (this conversion is selected by enumerating the applicable
conversion functions (13.3.1.6) and choosing the best one through
overload resolution (13.3)) [...]"

What does "can be implicitly converted to an lvalue of type =93cv3 T3,=94"
mean? There is the definition in 4/3:

"An expression e can be implicitly converted to a type T if and only
if the declaration T t=e; is well-formed, for some invented temporary
variable t (8.5)."

Note, however, that a reference cannot be called "variable" because
variable may denote only object (see 3/6) and reference is not an
object. The second issue is that we have to return to 8.5.3/5 again
and again recursively. Consider the following example:

struct X
{
   operator int &();
};

int f(int &);

int main()
{
   sizeof f(X());
}

X() is rvalue of class type, int is not reference-related to T. What
shall we do for checking the condition "X() can be implicitly
converted to an lvalue of type 'cv3 T3,' where 'int' is reference-
compatible with 'cv3 T3'"? According to 4/3 we have to consider the
following construct

cv3 T3 &t = X();

and determine whether it is well-formed. Because this is copy-
initialization of reference, we have to consider 8.5.3/5 again. X() is
still rvalue of class type and cv3 T3 cannot be reference-related to
T, so we shall check the new condition "X() can be implicitly
converted to an lvalue of type 'cv3_2 T3_2,' where 'cv3 T3' is
reference-compatible with 'cv3_2 T3_2'". This process is obviously
infinite.

There is other issue with informative footnote about conversion
functions. Consider the following example:

struct X
{
   operator X &();
};

int f(X &);

int main()
{
   sizeof f(X());
}

12.3.2/1 states:

"A conversion function is never used to convert a (possibly cv-
qualified) object to the (possibly cv-qualified) same object type (or
a reference to it), to a (possibly cvqualified) base class of that
type (or a reference to it), or to (possibly cv-qualified) void.
[Footnote 110: These conversions are considered as standard
conversions for the purposes of overload resolution (13.3.3.1,
13.3.3.1.4) and therefore initialization (8.5) and explicit casts
(5.2.9). [...] ]"

According to the footnote 110, the conversion from X() to X & is
considered as standard conversion for the purposes of overload
resolution. This is obviously wrong: "A standard conversion sequence
cannot be formed if it requires binding an lvalue reference to non-
const to an rvalue (except when binding an implicit object parameter;
see the special rules for that case in 13.3.1)." (see 13.3.3.1.4/3).


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





Author: litb <Schaub-Johannes@web.de>
Date: Sat, 29 Aug 2009 21:57:04 CST
Raw View
On 29 Aug., 01:19, Nikolay Ivchenkov <ts...@mail.ru> wrote:
> N2914 - 8.5.3/5 states:
> [...]
> What does "can be implicitly converted to an lvalue of type =93cv3 T3,=94"
> mean? There is the definition in 4/3:
>
> "An expression e can be implicitly converted to a type T if and only
> if the declaration T t=e; is well-formed, for some invented temporary
> variable t (8.5)."
>
> Note, however, that a reference cannot be called "variable" because
> variable may denote only object (see 3/6) and reference is not an
> object.
Agreed, there are very many issues with this variable/reference clash.
The madness also occurs at 8.5.3/1 "A variable declared to be a T& or
T&&, [...]", in description of "static_cast" (which contains a very
similar wording to that "implicitly converted" wording) and on other
places. A defect report exists here:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#633
. What i personally would like to see fixed before C++0x comes out:
This variable/reference clash, and the "declarative region" confusion:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#554

> There is other issue with informative footnote about conversion
> functions. Consider the following example:
>
> struct X
> {
>    operator X &();
>
> };
>
> int f(X &);
>
> int main()
> {
>    sizeof f(X());
>
> }
>
Note that this code is ill-formed.

> 12.3.2/1 states:
>
> "A conversion function is never used to convert a (possibly cv-
> qualified) object to the (possibly cv-qualified) same object type (or
> a reference to it), to a (possibly cvqualified) base class of that
> type (or a reference to it), or to (possibly cv-qualified) void.
> [Footnote 110: These conversions are considered as standard
> conversions for the purposes of overload resolution (13.3.3.1,
> 13.3.3.1.4) and therefore initialization (8.5) and explicit casts
> (5.2.9). [...] ]"
>
> According to the footnote 110, the conversion from X() to X & is
> considered as standard conversion for the purposes of overload
> resolution. This is obviously wrong: "A standard conversion sequence
> cannot be formed if it requires binding an lvalue reference to non-
> const to an rvalue (except when binding an implicit object parameter;
> see the special rules for that case in 13.3.1)." (see 13.3.3.1.4/3).
>
The binding of  "X&" to X() is an identity-conversion (a standard
conversion - not a standard conversion sequence). So, a user defined
conversion sequence cannot be formed,  because it would imply using
some user defined conversion (but this exact conversion is not
considered). So, it's tried to bind X() itself to "X&", for which no
conversion sequence can be formed. I don't see where here is a
contradiction.


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





Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Mon, 31 Aug 2009 09:56:11 CST
Raw View
On 30 Aug, 07:57, litb <Schaub-Johan...@web.de> wrote:
>
> The binding of  "X&" to X() is an identity-conversion (a standard
> conversion - not a standard conversion sequence).

Standard conversion is one of listed in 4.1 - 4.12. Standard
conversion sequence is a sequence (possibly empty) of standard
conversions. Identity conversion is a standard conversion sequence
that consists of no standard conversions (i.e. empty sequence).
Identity conversion cannot be considered as standard conversion.

See 4/1:

"A standard conversion sequence is a sequence of standard conversions
in the following
order:
- Zero or one conversion from the following set: lvalue-to-rvalue
conversion, array-to-pointer conversion, and function-to-pointer
conversion.
- Zero or one conversion from the following set: integral promotions,
floating point promotion, integral conversions, floating point
conversions, floating-integral conversions, pointer conversions,
pointer to member conversions, and boolean conversions.
- Zero or one qualification conversion.
[ Note: a standard conversion sequence can be empty, i.e., it can
consist of no conversions. -end note ]"

and 13.3.3.1.1/2:

"[ Note: As described in Clause 4, a standard conversion sequence is
either the Identity conversion by itself
(that is, no conversion) or consists of one to three conversions from
the other four categories. At most one
conversion from each category is allowed in a single standard
conversion sequence. If there are two or more
conversions in the sequence, the conversions are applied in the
canonical order: Lvalue Transformation,
Promotion or Conversion, Qualification Adjustment.    end note ]".

Conversion of rvalue of type X to lvalue of type X cannot be
considered as standard conversion nor standard conversion sequence,
except for binding an implicit object parameter - see 13.3.1/5 - in
this special case the standard conversion sequence is identity
conversion (but this is not a standard conversion).

> So, a user defined
> conversion sequence cannot be formed,  because it would imply using
> some user defined conversion (but this exact conversion is not
> considered). So, it's tried to bind X() itself to "X&", for which no
> conversion sequence can be formed.

The conversion function is not considered according to revised wording
in 8.5.3/5 - see DR 641:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#641


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