C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Compatible types and ternary operator
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Dylan Nicholson
Guest





PostPosted: Mon Jan 12, 2004 10:26 am    Post subject: Compatible types and ternary operator Reply with quote



Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

struct Base { };
struct Dev1 : Base { };
struct Dev2 : Base { };

bool foo();
Base* x = foo() ? new Dev1 : new Dev2;

It's just one of those things that's bugged me for a while, and I
figured there must be a good reason for it.

Dylan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Ron Natalie
Guest





PostPosted: Mon Jan 12, 2004 8:02 pm    Post subject: Re: Compatible types and ternary operator Reply with quote




"Dylan Nicholson" <wizofaus (AT) hotmail (DOT) com> wrote

Quote:
Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

No, it doesn't try to hunt down a common convertible type. All it
does (it's a bit more involved than this but this is the essence) see
if it can convert the first to the second and the second to the first.
If only one of those conversions is valid, then the converted type is
the value of the expression. Otherwise the program is ill-formed.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Mon Jan 12, 2004 8:11 pm    Post subject: Re: Compatible types and ternary operator Reply with quote



Dylan Nicholson wrote:
Quote:
Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

struct Base { };
struct Dev1 : Base { };
struct Dev2 : Base { };

bool foo();
Base* x = foo() ? new Dev1 : new Dev2;

It's just one of those things that's bugged me for a while, and I
figured there must be a good reason for it.

There is no requirement that a conditional expression be used as
the right-hand-side of an assignment expression. There are other
ways it can be used, and it would be hard to infer the expected
result type in other cases. The only case where the type of an
expression is inferred from its context is where the expression is
the name of an overloaded function or member function.

Also, note that in C++ (and in standard C) "lvalue" no longer
means an expression that is suitable for putting on the left of an
assignment operator. An lvalue is, to a first approximation, an
expression that evaluates to a function or object that isn't a
temporary (in the context in which it is used).

You can't assign to an lvalue of function type, non-const object
type, or of a user-defined type without an accessible assignment
operator. You an assign to an rvalue of user-defined type if has
an accessible assignment operator.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Craig Tiller
Guest





PostPosted: Tue Jan 13, 2004 10:23 am    Post subject: Re: Compatible types and ternary operator Reply with quote

I can see some use in the behaviour OP posted... any reason why it couldn't
be allowed?

"Ron Natalie" <ron (AT) sensor (DOT) com> wrote

Quote:

"Dylan Nicholson" <wizofaus (AT) hotmail (DOT) com> wrote

Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

No, it doesn't try to hunt down a common convertible type. All it
does (it's a bit more involved than this but this is the essence) see
if it can convert the first to the second and the second to the first.
If only one of those conversions is valid, then the converted type is
the value of the expression. Otherwise the program is ill-formed.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dylan Nicholson
Guest





PostPosted: Tue Jan 13, 2004 10:25 am    Post subject: Re: Compatible types and ternary operator Reply with quote

"Ron Natalie" <ron (AT) sensor (DOT) com> wrote

Quote:
"Dylan Nicholson" <wizofaus (AT) hotmail (DOT) com> wrote

Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

No, it doesn't try to hunt down a common convertible type. All it
does (it's a bit more involved than this but this is the essence) see
if it can convert the first to the second and the second to the first.
If only one of those conversions is valid, then the converted type is
the value of the expression. Otherwise the program is ill-formed.

I'm aware of *what* the rule is, just wondering historically why it is

that way. It seems an odd sort of limitation. I can't think of any
obvious reason why the ternary operator should be treated as anything
other than a short-cut to an if-else.

Dylan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dylan Nicholson
Guest





PostPosted: Tue Jan 13, 2004 10:30 am    Post subject: Re: Compatible types and ternary operator Reply with quote

Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> wrote

Quote:
Dylan Nicholson wrote:
Hi

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the ternary
operator?
I would have thought it was sufficient that the types were convertible
to the l-value, so the following should (in theory) be perfectly safe:

struct Base { };
struct Dev1 : Base { };
struct Dev2 : Base { };

bool foo();
Base* x = foo() ? new Dev1 : new Dev2;

It's just one of those things that's bugged me for a while, and I
figured there must be a good reason for it.

There is no requirement that a conditional expression be used as
the right-hand-side of an assignment expression. There are other
ways it can be used, and it would be hard to infer the expected
result type in other cases. The only case where the type of an
expression is inferred from its context is where the expression is
the name of an overloaded function or member function.

I suppose I can see that the concept of a 'lazily-evaluted' type is

not part of C++, even at compile-time. Seeing as there's no
completely obvious straightforward method of defining exactly what the
type of a ternary expression result is unless both types are
inter-convertible, it's probably better the way it is. From a
programmer point of view it's a pretty minor inconvenience.

A related question - is there a type of cast in C++ that is always
safe?
eg.

Base* x = foo() ? safe_cast<Base*>(new Dev1) : safe_cast<Base*>(new
Dev2);

I guess what I'm looking for is a cast that only compiles if an
implicit conversion or cast operator is available.

Dylan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Tue Jan 13, 2004 3:21 pm    Post subject: Re: Compatible types and ternary operator Reply with quote

Dylan Nicholson wrote:
<snip>
Quote:
A related question - is there a type of cast in C++ that is always
safe?

That depends on what you mean by safe. ;-)

Quote:
eg.

Base* x = foo() ? safe_cast<Base*>(new Dev1) : safe_cast<Base*>(new
Dev2);

I guess what I'm looking for is a cast that only compiles if an
implicit conversion or cast operator is available.

No, there isn't. It has been proposed before as "implicit_cast" or
"safe_cast" but didn't make it into the last standard. You can
define a somewhat useful version as a function template:

template<typename T>
inline T std_convert(T value)
{
return value;
}

Note that the function doesn't really do any conversion.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Wed Jan 14, 2004 10:10 am    Post subject: Re: Compatible types and ternary operator Reply with quote

Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> wrote

Quote:
Dylan Nicholson wrote:

Just wondering if anyone knew the reasoning behind why compatible
types are required between the two alternatives when using the
ternary operator?
I would have thought it was sufficient that the types were
convertible to the l-value, so the following should (in theory) be
perfectly safe:

I don't understand the business about l-value. What is required (more
or less) is that one of the types be convertable to the other.

Quote:
struct Base { };
struct Dev1 : Base { };
struct Dev2 : Base { };

bool foo();
Base* x = foo() ? new Dev1 : new Dev2;

It's just one of those things that's bugged me for a while, and I
figured there must be a good reason for it.

There is no requirement that a conditional expression be used as the
right-hand-side of an assignment expression. There are other ways it
can be used, and it would be hard to infer the expected result type in
other cases. The only case where the type of an expression is
inferred from its context is where the expression is the name of an
overloaded function or member function.

That's not needed, however. While it would certainly be more difficult
for compiler writers (and more difficult to specify for the authors of
the standard), it would be possible to say something along the lines
that if both E1 and E2 have (possibly const-qualified) pointer to class
types, and both classes have a common base, the highest common base is
the common type. Of course, you would then have to specify things like
what happens in the case of multiple inheritance, etc. And what happens
with lvalues and references :

Dev1 d1 ;
Dev2 d2 ;
Base& b = foo() ? d1 : d2 ;

IMHO, it would be a useful extension. But not easy to correctly
specify, and probably not very easy for compiler writers to implement.

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Frank Birbacher
Guest





PostPosted: Wed Jan 14, 2004 10:27 am    Post subject: Re: Compatible types and ternary operator Reply with quote

Hi!

Ben Hutchings wrote:
Quote:
template<typename T
inline T std_convert(T value)
{
return value;
}

Note that the function doesn't really do any conversion.

Which could be changed:

template inline TTo safe_cast(TFrom from)
{
return from;
}

Frank


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Wed Jan 14, 2004 11:03 pm    Post subject: Re: Compatible types and ternary operator Reply with quote

Frank Birbacher wrote:
Quote:
Ben Hutchings wrote:
template inline T std_convert(T value)
{
return value;
}

Note that the function doesn't really do any conversion.

Which could be changed:

template inline TTo safe_cast(TFrom from)
{
return from;
}

If this is specialised with TTo = B* and TFrom = D*, where D inherits
privately from B, the conversion is inaccessible and so the program
is ill-formed. However, D's members and friends should be able to
convert D* to B*, which they will be able to if conversion is done
implicitly in the calling function. (I didn't spot this; credit is
due to someone whose article I can no longer find.)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Mike Bland
Guest





PostPosted: Thu Jan 15, 2004 10:33 am    Post subject: Re: Compatible types and ternary operator Reply with quote

On 2004-01-13, Dylan Nicholson <wizofaus (AT) hotmail (DOT) com> wrote:
Quote:
A related question - is there a type of cast in C++ that is always
safe?
eg.

Base* x = foo() ? safe_cast<Base*>(new Dev1) : safe_cast<Base*>(new
Dev2);

I guess what I'm looking for is a cast that only compiles if an
implicit conversion or cast operator is available.

Isn't this pretty much what static_cast does? At least, if your idea
of "safety" means a safe cast for pointer types from derived to base
classes, or for types for which a conversion constructor or operator
is available?

Mike



-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Matthias Hofmann
Guest





PostPosted: Fri Jan 23, 2004 10:20 am    Post subject: Re: Compatible types and ternary operator Reply with quote

Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> schrieb in im Newsbeitrag:
[email]slrnc0aok4.vo.do-not-spam-benh (AT) tin (DOT) bwsint.com[/email]...
Quote:
Frank Birbacher wrote:
Ben Hutchings wrote:

[snip]

Quote:

template inline TTo safe_cast(TFrom from)
{
return from;
}

If this is specialised with TTo = B* and TFrom = D*, where D inherits
privately from B, the conversion is inaccessible and so the program
is ill-formed. However, D's members and friends should be able to
convert D* to B*, which they will be able to if conversion is done
implicitly in the calling function. (I didn't spot this; credit is
due to someone whose article I can no longer find.)


I do not quite understand what you mean by "implicitly in the calling
function" - did you mean to write "explicitly"? Or did you mean to write "in
the called function"? Otherwise, if D* can be converted to B* explicitly in
the calling function, why shouldn't it work within safe_cast()?

Best regards,

Matthias




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Fri Jan 23, 2004 9:09 pm    Post subject: Re: Compatible types and ternary operator Reply with quote

Matthias Hofmann wrote:
Quote:
Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> schrieb in im Newsbeitrag:
[email]slrnc0aok4.vo.do-not-spam-benh (AT) tin (DOT) bwsint.com[/email]...
Frank Birbacher wrote:
Ben Hutchings wrote:

[snip]


template inline TTo safe_cast(TFrom from)
{
return from;
}

If this is specialised with TTo = B* and TFrom = D*, where D inherits
privately from B, the conversion is inaccessible and so the program
is ill-formed. However, D's members and friends should be able to
convert D* to B*, which they will be able to if conversion is done
implicitly in the calling function. (I didn't spot this; credit is
due to someone whose article I can no longer find.)

I do not quite understand what you mean by "implicitly in the calling
function" - did you mean to write "explicitly"? Or did you mean to write "in
the called function"?

I do mean "implicitly". The conversion can be done as part of
parameter initialisation in the calling function (5.2.2/4).

Quote:
Otherwise, if D* can be converted to B* explicitly in
the calling function, why shouldn't it work within safe_cast()?

Because D inherits privately from B and safe_cast isn't a member or
friend of D.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Matthias Hofmann
Guest





PostPosted: Sat Jan 24, 2004 9:47 pm    Post subject: Re: Compatible types and ternary operator Reply with quote


Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> schrieb in im Newsbeitrag:
[email]slrnc1258i.104.do-not-spam-benh (AT) tin (DOT) bwsint.com[/email]...
Quote:
Matthias Hofmann wrote:
Ben Hutchings <do-not-spam-benh (AT) bwsint (DOT) com> schrieb in im Newsbeitrag:
[email]slrnc0aok4.vo.do-not-spam-benh (AT) tin (DOT) bwsint.com[/email]...
Frank Birbacher wrote:
Ben Hutchings wrote:

[snip]


template inline TTo safe_cast(TFrom from)
{
return from;
}

If this is specialised with TTo = B* and TFrom = D*, where D inherits
privately from B, the conversion is inaccessible and so the program
is ill-formed. However, D's members and friends should be able to
convert D* to B*, which they will be able to if conversion is done
implicitly in the calling function. (I didn't spot this; credit is
due to someone whose article I can no longer find.)

I do not quite understand what you mean by "implicitly in the calling
function" - did you mean to write "explicitly"? Or did you mean to write
"in
the called function"?

I do mean "implicitly". The conversion can be done as part of
parameter initialisation in the calling function (5.2.2/4).

I feel a little stoopid asking back again, but I am still confused - you
said that TFrom = D*, so how does parameter initialization cause any
conversion? Aren't you passing a D* anyway? Maybe a short code example would
help me understand... :-)

Best regards,

Matthias




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Sun Jan 25, 2004 10:52 am    Post subject: Re: Compatible types and ternary operator Reply with quote

On 24 Jan 2004 16:47:00 -0500, "Matthias Hofmann"
<hofmann (AT) anvil-soft (DOT) com> wrote:


Quote:
Maybe a short code example would help me understand.

template<typename TTo, typename TFrom>
inline TTo safe_cast(TFrom from) { return from; }
struct B { };
void f (B const*) { }
struct D : private B {
void g () const { f(this); }
void h () const { f(safe_cast<B*>(this)); }
};
void g (D const* d) { f(d); }
void h (D const* d) { f(safe_cast<B*>(d)); }

The implicit conversion in member g is the only valid call of f.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.