C++ Logo


Advanced search

Reference initialization (CWG1604)

From: Maris Razvan <razvyboy2004_at_[hidden]>
Date: Fri, 9 Oct 2020 17:34:35 +0300

I was reading paragraph 5 of [dcl.init.ref] from the current draft of
the C++ standard (which describes reference initialization),
specifically bullet 4, sub-bullet 1, which says:

    "If T1 or T2 is a class type and T1 is not reference-related to
T2, user-defined conversions are considered using the rules for
copy-initialization of an object of type “cv1 T1” by user-defined
conversion ([dcl.init], [over.match.copy], [over.match.conv]); the
program is ill-formed if the corresponding non-reference
copy-initialization would be ill-formed. The result of the call to the
conversion function, as described for the non-reference
copy-initialization, is then used to direct-initialize the reference.
For this direct-initialization, user-defined conversions are not

I think some of the wording in this sub-bullet is not necessary, and
this wording was added by the resolution to CWG1604

1. The main issue that I have with the quoted sub-bullet is the last
sentence: "For this direct-initialization, user-defined conversions
are not considered.".
This restriction is similar to the one specified in
[over.best.ics.general] paragraph 4, bullet 3.

However, I believe that in this context, this restriction does not
have to be explicitly stated, as user-defined conversions will not be
used in the "second stage" of the reference initialization even
without this sentence.
This is because the type that results from [over.match.copy] or
[over.match.conv] (henceforth referred to as T3) is:

    - T1 or a type derived from T1 (in case T1 is a class type;
[over.match.copy]), or
    - T1 or a type that can be converted to T1 using a standard
conversion sequence (in case T1 is not a class type;

Only the first case (T1 is a class type) is of interest (otherwise
user-defined conversions are excluded by default in the "second stage"
of the initialization). T3 is reference-related to T1, and
[dcl.init.ref] paragraph 5 only considers user-defined conversions in
case the reference type and the initializer type are not
reference-related. Therefore explicitly disallowing user-defined
conversions in the "second stage" of the reference initialization is
not required.

Also, I think that even considering the state of the standard when the
resolution for CWG1604 was introduced, this restriction did not have
to be explicitly mentioned.
The relevant differences between the standard back then and the
current standard are:
    - candidates from [over.match.conv] were not considered in this sub-bullet
    - this sub-bullet was not conditioned on T1 and T2 not being
reference-related (however, if the "second stage" of the
initialization were to reach it, the program would be ill-formed due
to other restrictions, i.e. cv1 T1 (type of the reference) has to be
more cv-qualified than cv2 T2 (type of the initializer) and lvalue
initializers are not allowed for rvalue references)

Am I not taking into account some cases for which this restriction has
to be explicitly mentioned?

2. Another issue that I have with the quoted sub-bullet is that I
believe requiring a specific type of initialization (i.e.
direct-initialization) for the "second stage" of the reference
initialization is not necessary, as user-defined conversions are not
allowed (as discussed above, both by the last sentence of this
sub-bullet and by the other rules in this paragraph). And the only
difference between copy-initialization and direct-initialization in
this situation would be whether explicit user-defined conversions are
considered or not.

Are there some cases that I am missing, for which this distinction
makes a difference?

3. The last and least significant issue regarding this paragraph is
the wording: "The result of the call to the conversion function
[...]". I think the user-defined conversion used here could be either
a converting constructor or a conversion function, not just a
conversion function, no?

I have created an issue regarding these 3 problems on the github page
of the C++ standard draft:

Thank you!

Received on 2020-10-09 09:34:49