Topic: can explicit qualifiers ambiguity?
Author: musiphil@bawi.org (Seungbeom Kim)
Date: Wed, 18 Feb 2004 13:36:31 +0000 (UTC) Raw View
Francis Glassborow wrote:
>
> However this is just one more case where there are different semantics
> for the two initialisation styles. I think those differences are
> gratuitous and we should consider removing them. Is there any good
> reason not to make the two forms entirely interchangeable (apart from
> the assignment form not having the potential for ambiguity with function
> declarations.) I think I would like to consider going even further and
> consider how to bring the third syntactic form (brace initialisation of
> aggregates) into the fold. BTW why exactly do we limit that syntactic
> form to C-style aggregates?
I agree. I guess many of us would like to write
string s = "Hello, world!";
without worrying about copies. For fundamental types, it is so
natural to say "int i=0;" and we don't feel obliged to write
"int i(0);" just because of efficiency reasons. I'd like to see
the same thing apply to user-defined types. Why would we have to
feel obliged to write 'string s("Hello, world!");'? Isn't it silly?
Your suggestion regarding the brace form seems interesting.
Do you mean something like
complex<int> c = {re, im};
instead of
complex<int> c(re, im);
? I'll have ponder upon it, but at first sight it looks attractive.
--
Seungbeom Kim
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 19 Feb 2004 19:59:57 +0000 (UTC) Raw View
In article <40331263.9660E682@bawi.org>, Seungbeom Kim
<musiphil@bawi.org> writes
>I agree. I guess many of us would like to write
>
> string s = "Hello, world!";
>
>without worrying about copies. For fundamental types, it is so
>natural to say "int i=0;" and we don't feel obliged to write
>"int i(0);" just because of efficiency reasons. I'd like to see
>the same thing apply to user-defined types. Why would we have to
>feel obliged to write 'string s("Hello, world!");'? Isn't it silly?
>
>Your suggestion regarding the brace form seems interesting.
>Do you mean something like
>
> complex<int> c = {re, im};
>
>instead of
>
> complex<int> c(re, im);
>
>? I'll have ponder upon it, but at first sight it looks attractive.
I would consider rather more. For example (purely for the purposes of
explanation):
class mytype {
int data[10];
public:
mytype(int * array): data = array {}
};
int main(){
mytype mt({3, 5, 6});
}
Note that a great deal of detail would need to be worked out. The
semantics is fairly easy but the syntax needs much work.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: wizofaus@hotmail.com (Dylan Nicholson)
Date: Fri, 20 Feb 2004 02:11:06 +0000 (UTC) Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote in message news:<VdJMDiaIO3MAFwpH@robinton.demon.co.uk>...
>
> I would consider rather more. For example (purely for the purposes of
> explanation):
>
> class mytype {
> int data[10];
> public:
> mytype(int * array): data = array {}
> };
>
> int main(){
> mytype mt({3, 5, 6});
> }
>
> Note that a great deal of detail would need to be worked out. The
> semantics is fairly easy but the syntax needs much work.
>
Well without even changing the syntax, the following could be
supported:
class mytype
{
int data[10];
public:
mytype(int array[3]) : data(array) { }
};
int main()
{
static const int init[3] = { 3, 5, 6 };
mytype mt(init);
}
The ability to just write
mytype mt({3, 5, 6});
would be nice, but I don't think it's worth having to rewrite C/C++
parsers just for this.
Dylan
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Wed, 11 Feb 2004 04:55:10 +0000 (UTC) Raw View
Consider:
class X
{
public:
X(short s)
{}
explicit X(long l)
{}
};
int main()
{
X x(3); //A
X y=3; //B
}
Much to my surprise two compilers reject line A (ambiguity) as I expect
but accept line B resolving in favour of the non-explicit ctor. My gut
reaction is that this is wrong. If it isn't what in the Standard
supports it? (the compilers in question seem to be excluding explicit
ctors from the overload set for implicit conversions)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: technews@kangaroologic.com ("Jonathan Turkanis")
Date: Wed, 11 Feb 2004 14:53:51 +0000 (UTC) Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:y30lZZBlXLKAFw+T@robinton.demon.co.uk...
>
> Consider:
>
> class X
> {
> public:
> X(short s)
> {}
> explicit X(long l)
> {}
> };
>
> int main()
> {
> X x(3); //A
> X y=3; //B
> }
>
> Much to my surprise two compilers reject line A (ambiguity) as I
expect
> but accept line B resolving in favour of the non-explicit ctor. My
gut
> reaction is that this is wrong. If it isn't what in the Standard
> supports it? (the compilers in question seem to be excluding
explicit
> ctors from the overload set for implicit conversions)
>
I'll interpret the subject line as 'Can explicit qualifiers prevent
ambiguity?' ;-)
The two compilers you tried are right. (The only compiler I found
which rejected B was Intel 7.1 for Windows, but this was fixed with
8.0). The governing language, I believe, is the last bulleted sub-item
of the fourth bulleted item of 8.5/14:
"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)."
12.3.1 makes clear that only non-explicit constructors give rise to
user-defined conversions, so for the purposes of 8.5/14, only the
first X constructor in your example should be considered.
Jonathan
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: rani_sharoni@hotmail.com ("Rani Sharoni")
Date: Wed, 11 Feb 2004 14:53:54 +0000 (UTC) Raw View
Francis Glassborow wrote:
> Consider:
>
> class X
> {
> public:
> X(short s)
> {}
> explicit X(long l)
> {}
> };
>
> int main()
> {
> X x(3); //A
> X y=3; //B
> }
>
> Much to my surprise two compilers reject line A (ambiguity) as I
> expect but accept line B resolving in favour of the non-explicit
> ctor. My gut reaction is that this is wrong. If it isn't what in the
> Standard supports it? (the compilers in question seem to be excluding
> explicit ctors from the overload set for implicit conversions)
12.3.1/3:
A non-explicit copy-constructor (12.8) is a converting constructor.
13.3.1.3/1: Initialization by constructor
For direct-initialization, the candidate functions are all the
*constructors* of the class of the object being initialized.
For copy-initialization, the candidate functions are all the *converting
constructors* (12.3.1) of that class.
Rani
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: mats.kindahl@nowhere.net (Mats Kindahl)
Date: Wed, 11 Feb 2004 17:29:01 +0000 (UTC) Raw View
francis@robinton.demon.co.uk (Francis Glassborow) writes:
> Consider:
>
> class X
> {
> public:
> X(short s)
> {}
> explicit X(long l)
> {}
> };
>
> int main()
> {
> X x(3); //A
> X y=3; //B
> }
>
> Much to my surprise two compilers reject line A (ambiguity) as I expect
> but accept line B resolving in favour of the non-explicit ctor. My gut
> reaction is that this is wrong. If it isn't what in the Standard
> supports it? (the compilers in question seem to be excluding explicit
> ctors from the overload set for implicit conversions)
I've been bitten by that one quite a few times. :/
According to 8.5 point 14, the expression A uses a
_direct-initializer_, while the second expression B uses a
_copy-initializer_ and performs an implicit (user-defined) conversion
of 3 to X using the only constructor available for this conversion,
namely X::X(short).
You find a short note under 8.5 point 11 noting that there is a
difference between line A and line B above and you find the definition
of copy-initialization and direct-initialization under point 12.
About your last comment: paragraph 13.3.1.4 explicitly says that only
_converting constructors_ (that is, constructors that can be called
with a single argument and that does not have the "explicit" keyword
[12.3.1]) are candidate functions for copy-initializations of a class
by user-defined conversions.
Best wishes,
Mats Kindahl
--
IAR Systems in Uppsala, Sweden.
Any opinions expressed are my own and not those of my company.
Spam prevention: contact me at mNaOtSkPiAnM@acm.org or
mNaOtSs.kPindAahMl@iar.se, removing the *NO SPAM* from the address.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: anthony.williamsNOSPAM@anthonyw.cjb.net (Anthony Williams)
Date: Wed, 11 Feb 2004 17:29:12 +0000 (UTC) Raw View
francis@robinton.demon.co.uk (Francis Glassborow) writes:
> Consider:
>
> class X
> {
> public:
> X(short s)
> {}
> explicit X(long l)
> {}
> };
>
> int main()
> {
> X x(3); //A
> X y=3; //B
> }
>
> Much to my surprise two compilers reject line A (ambiguity) as I expect
> but accept line B resolving in favour of the non-explicit ctor. My gut
> reaction is that this is wrong. If it isn't what in the Standard
> supports it? (the compilers in question seem to be excluding explicit
> ctors from the overload set for implicit conversions)
Francis already knows my opinion, but for those that don't...
I think the compilers are right to allow line B as they do; I believe this
position is supported by the Standard.
For copy initialization, we need to see 8.5p14, which says
"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)."
13.3.1.4 says:
"the candidate functions are selected as follows:
- The converting constructors (12.3.1) of T are candidate functions."
12.3.1 says:
"A constructor declared without the function-specifier explicit that can be
called with a single parameter specifies a conversion from the type of its
first parameter to the type of its class. Such a constructor is called a
converting constructor."
So, copy initialization only considers converting constructors, and explicit
constructors are not converting constructors. Therefore explicit constructors
are not considered, line B is legal, and resolves to the non-explicit
constructor.
Anthony
--
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dag_henriksson@hotmail.com ("Dag Henriksson")
Date: Thu, 12 Feb 2004 04:33:07 +0000 (UTC) Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> skrev i meddelandet
news:y30lZZBlXLKAFw+T@robinton.demon.co.uk...
>
> Consider:
>
> class X
> {
> public:
> X(short s)
> {}
> explicit X(long l)
> {}
> };
>
> int main()
> {
> X x(3); //A
> X y=3; //B
> }
>
> Much to my surprise two compilers reject line A (ambiguity) as I expect
> but accept line B resolving in favour of the non-explicit ctor. My gut
> reaction is that this is wrong. If it isn't what in the Standard
> supports it? (the compilers in question seem to be excluding explicit
> ctors from the overload set for implicit conversions)
12.3.1p1 tells us that explicit X(long l) is not a converting constructor:
"[class.conv.ctor] 12.3.1 Conversion by constructor
1 A constructor declared without the function-specifier explicit that can be
called with a single parameter specifies a conversion from the type of its
first parameter to the type of its class. Such a constructor is called a
converting constructor."
and 13.3.1.4p1 tells us that only converting constructors are candidate
function in the overload resolution in the context of 'B' above:
13.3.1.4p1
"Assuming that "cv1 T" is the type of the object being initialized, with T a
class type, the candidate functions are selected as follows:
- The converting constructors (12.3.1) of T are candidate functions."
--
Dag Henriksson
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 12 Feb 2004 04:33:14 +0000 (UTC) Raw View
In article <4029ff1e$1@news.microsoft.com>, Rani Sharoni
<rani_sharoni@hotmail.com> writes
>Francis Glassborow wrote:
>> Consider:
>>
>> class X
>> {
>> public:
>> X(short s)
>> {}
>> explicit X(long l)
>> {}
>> };
>>
>> int main()
>> {
>> X x(3); //A
>> X y=3; //B
>> }
>>
>> Much to my surprise two compilers reject line A (ambiguity) as I
>> expect but accept line B resolving in favour of the non-explicit
>> ctor. My gut reaction is that this is wrong. If it isn't what in the
>> Standard supports it? (the compilers in question seem to be excluding
>> explicit ctors from the overload set for implicit conversions)
>
>12.3.1/3:
>A non-explicit copy-constructor (12.8) is a converting constructor.
>
>13.3.1.3/1: Initialization by constructor
>For direct-initialization, the candidate functions are all the
>*constructors* of the class of the object being initialized.
>For copy-initialization, the candidate functions are all the *converting
>constructors* (12.3.1) of that class.
After posting the original I pieced that lot together. Now I wonder if
that was intentional when we wrote those words because it results in
quite a surprise. The surprise is not so much that an explicit
constructor is not a conversion mechanism but that the assignment style
syntax can let through a narrowing conversion without diagnostic when
the function style syntax generates a diagnostic. Of course we could
criticise the designer of X in the above case for not making both
explicit.
However this is just one more case where there are different semantics
for the two initialisation styles. I think those differences are
gratuitous and we should consider removing them. Is there any good
reason not to make the two forms entirely interchangeable (apart from
the assignment form not having the potential for ambiguity with function
declarations.) I think I would like to consider going even further and
consider how to bring the third syntactic form (brace initialisation of
aggregates) into the fold. BTW why exactly do we limit that syntactic
form to C-style aggregates?
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: rani_sharoni@hotmail.com ("Rani Sharoni")
Date: Fri, 13 Feb 2004 22:13:38 +0000 (UTC) Raw View
Francis Glassborow wrote:
> In article <4029ff1e$1@news.microsoft.com>, Rani Sharoni
> <rani_sharoni@hotmail.com> writes
>> Francis Glassborow wrote:
>>> Much to my surprise two compilers reject line A (ambiguity) as I
>>> expect but accept line B resolving in favour of the non-explicit
>>> ctor. My gut reaction is that this is wrong. If it isn't what in the
>>> Standard supports it? (the compilers in question seem to be
>>> excluding explicit ctors from the overload set for implicit
>>> conversions)
>>
>> 12.3.1/3:
>> A non-explicit copy-constructor (12.8) is a converting constructor.
>>
>> 13.3.1.3/1: Initialization by constructor
>> For direct-initialization, the candidate functions are all the
>> *constructors* of the class of the object being initialized.
>> For copy-initialization, the candidate functions are all the
>> *converting constructors* (12.3.1) of that class.
> [...]
> However this is just one more case where there are different semantics
> for the two initialisation styles. I think those differences are
> gratuitous and we should consider removing them. Is there any good
> reason not to make the two forms entirely interchangeable (apart from
> the assignment form not having the potential for ambiguity with
> function declarations.)
I totally agree with you that both form of initialization should be
*equivalent*. All the cases in which the behavior is different are
surprising and I don't expect the poor programmer to survive such subtleties
(i.e. knowing what the code is actually doing). OTOH I don't see what the
benefit is from such distinguish. For example (variation on your code):
struct A {
explicit A(int);
A(double);
};
// direct initialization using A::A(int)
A var1(10);
// copy initialization using A::A(double)
// A::A(double) creates temporary that used
// to initialize the target object using
// direct initialization.
// The required call to copy ctor might be
// eliminated and all compilers actually do it.
A var2 = 10;
I think the intention behind "explicit" is to forbid specified conversion in
the true sense of copy initialization which is passing parameter:
int f(A);
int x = f(10);
I (also) never fully understood why does the copy initialization process
requires additional call to a copy constructor that later is practically
eliminated. Maybe it's related to some historical limitation of compilers.
Anyway, making such core language changes might break existing code which
makes a bit more problematic than ordinary relaxation.
> I think I would like to consider going even
> further and consider how to bring the third syntactic form (brace
> initialisation of aggregates) into the fold.
Aggregates initialization using the C-style form is copy-initialization (for
each member) yet, in this case, the implicit conversion might not be noticed
by someone that reads the code.
> BTW why exactly do we
> limit that syntactic form to C-style aggregates?
Maybe to limit the usage of this old syntactic form.
Thanks,
Rani
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]