Topic: Proposal for a change in copy initialization
Author: "Ofer Porat" <oporat@yahoo.com>
Date: Thu, 12 Jul 2007 12:38:18 CST Raw View
Here is proposed wording for this change (based on N2315)
In [dcl.init]/15, the subparagraph that beings with the text
"- Otherwise (i.e., for the remaining copy-initialization cases), ..."
replace with
"- Otherwise (i.e., for the remaining copy-initialization cases),
user-defined conversion sequences that can convert from the source type
to the destination type or (when a conversion function is used) to a
derived class thereof are enumerated as described in 13.3.1.4, and the
best one is chosen through overload resolution (13.3). If the conversion
cannot be done or is ambiguous, the initialization is ill-formed. The
function selected is called with the initializer expression as its
argument; if the function is a constructor, the destination is
direct-initialized by calling the selected constructor. Otherwise, the
result of the call is used to direct-initialize, according to the rules
above, the object that is the destination of the copy-initialization. In
certain cases, an implementation is permitted to eliminate the copying
inherent in this direct-initialization by constructing the intermediate
result directly into the object being initialized; see 12.2, 12.8."
Ofer Porat
oporat@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.comeaucomputing.com/csc/faq.html ]
Author: oporat@yahoo.com (Ofer Porat)
Date: Mon, 25 Jun 2007 16:21:40 GMT Raw View
Consider the initialization "T t = e" where T is a class type.
In N2284, an initialization of this type is covered by section 8.5
[dcl.init] clause 15 and in greater detail in sections 13.3.1.3
[over.match.ctor] and 13.3.1.4 [over.match.copy].
Let E by the type of the expression e. There are basically 3 cases for
handling the initialization:
Case 1)
- E is T or a derived class of T.
- T has a converting constructor that can convert E to T.
In this case t is constructed directly from e by using the converting
constructor.
Case 2)
- E is neither T nor derived from T.
- T has a converting constructor that can convert E to T.
- T has a copy constructor.
In this case, t is constructed as follows
2a] the converting constructor is used to create a temporary of type T.
2b] the temporary is copied into t using T's copy constructor.
2c] the copy may be elided, but as with any elision, an access check
must be done.
Case 3)
- E is neither T nor derived from T.
- E is a class type. Either E or one of its bases has a conversion
function that can convert E to a type T_D which is either T or derived
from T.
- T has a constructor that can initialize T from T_D.
In this case, t is constructed as follows
3a] the conversion function is used to create a temporary of type T_D.
3b] the temporary is used to initialize t using the constructor.
3c] if T_D == T, the copy may be elided, but as with any elision, an
access check must be done.
My concern is with Case 2. First, it's clear that the
copy-construction in 2b can always be elided, since step 2a is itself a
constructor-call and there's no reason why the construction in 2a can't
be carried out directly into t.
If we compare with Case 3, it's not clear that the copy can be elided
as mentioned in 3c, since not every implementation can be expected to
be able to construct a function return value directly into a desired
target object.
However, since 2a already uses a constructor, it should always be
possible to elide the copy.
The effect of having Case 2) designed the way it is, means that if T is
a noncopyable class (e.g. copy constructor is private), that makes the
copy-initialization invalid when E is not derived from T. There's no
reason for it to be invalid if T has a converting constructor accepting
E. If T has such a constructor, it's not evident from the form "T t =
e" that it should involve any kind of copy construction at all.
It's possible of course to overcome this by using direct initialization
("T t(e)"). However, the form "T t(e)" can be mistaken for a function
declaration for some forms of e. In that case, copy initialization is
sometimes used to disambiguate. But if T is noncopyable, this method
of disambiguation fails...
I propose that Case 1) and Case 2) be folded into one which is to say
Case 1+2 combined)
- If T has a converting constructor that can convert E to T then t is
constructed directly from e by using the converting constructor.
Ofer Porat
oporat@yahoo.com
____________________________________________________________________________________
Got a little couch potato?
Check out fun summer activities for kids.
http://search.yahoo.com/search?fr=oni_on_mail&p=summer+activities+for+kids&cs=bz
---
[ 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 ]