Re: initialization of function argument
On Nov 26, 11:52 am, "Alf P. Steinbach" <al...@start.no> wrote:
* James Kanze:
[...]
I don't think so, but the original standard is far from clear.
In the section on initialization, it makes it very clear that if
the initialization expression in copy initialization has the
same type as, or a type derived from, the target type, the
semantics are the same as those of direct initialization. In
the section concerning explicit, on the other hand, the latest
draft says that an explicit constructor will only be used "where
the direct-initialization syntax (8.5) or where casts (5.2.9,
5.4) are explicitly used."
This is also the language of the original standard.
It's not a contradiction: "explicit" is a limitation on
allowable syntax for constructor calls, namely that they must
be explicit, and is not concerned with the final semantic
effect of a call.
In other words, =A78.5 on initialization refers to the semantic effect,
whereas =A712.3.1 on explicit constructors refers to which syntax syntax
is allowed.
That does sound like the most reasonable interpretation. (Of
what is written, not of what should be specified.)
Only in the cases where explicit constructor call syntax is
not available (the only such case I know is passing an
argument by value) does that limit what can be done, the
possible semantics.
There is no such thing as an "explicit constructor call syntax".
Or are you using this as a synonym for "direct-initialization
syntax or casts"?
At any rate, another case would be return values, and I think
some cases involved in exceptions (catching by value, certainly,
but what about the copy which takes place during a throw?).
[...]
The simplest solution is just to never declare the copy
constructor explicit. (Since explicit is designed to prevent
conversions, and the copy constructor doesn't "convert" anything
in the classical sense of the word, the logical decision would
have been for explicit to be ignored on the copy constructor.)
That would introduce another special case (in addition to the default
constructor), and this time on the argument type. Which would either be
inconsistent with effect of -- I'm assuming this is allowed --
template< class T >
explicit MyClass( T const & );
or make this templated non-copy constructor allow different call
/syntax/ dependending on the actual argument /type/.
It's messy.
Yup. More than I realized at first glance. On the other hand,
it would allow the simple rule of always declaring constructors
explicit, without worrying about whether they might be used for
copy or not.
Your template example suggests an even more pernitious example
to me:
class Toto
{
public:
Toto( Toto& other ) ;
template< typename T >
explicit Toto( T const& other ) ;
} ;
void f( Toto ) ;
void
g()
{
Toto t1 ;
Toto const t2 ;
f( t1 ) ; // no problem...
f( t2 ) ; // illegal! even though a copy is passed.
}
Off hand, I'd say that your example with the template is even
more of an argument that something isn't right. That explicit
should probably only have an effect when an implicit conversion
is involved, and should be ignored otherwise. (But I'm not sure
how to express that in standardese.)
I think perhaps the decision to mix construction and
conversion in one common syntax was not optimal,
I think that there's more or less general agreement about this
now. It's a historical issue.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34