Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Defect: Missing fundamental feature!

0 views
Skip to first unread message

Frederick Gotham

unread,
Jun 16, 2006, 1:29:08 PM6/16/06
to

About a year or two ago, I started searching the internet for some code
which implements a "typeof" operator, and I came up with a few template
near-solutions.

There are quite a few inherent problems with C++ which can be solved with
templates, and once such a template has been devised (e.g. boost's
"implict_cast"), people tend to pipe down about it.

Today, I again found myself wanting a "typeof" operator, and I find it
ludicrous that the language doesn't provide such basic functionality.

A "typeof" operator should be very like the "sizeof" operator, in that it
doesn't evaluate the expression.

Two things which I think should be a concrete feature in the language
(rather than achieved with template cleverness) are:

typeof
implicit_cast


Are there intentions to add these to the language?


--

Frederick Gotham

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

Victor Bazarov

unread,
Jun 16, 2006, 2:21:09 PM6/16/06
to
Frederick Gotham wrote:
> About a year or two ago, I started searching the internet for some
> code which implements a "typeof" operator, and I came up with a few
> template near-solutions.
>
> [..]

> Are there intentions to add these to the language?

"typeof": http://www.research.att.com/~bs/n1705-decltype.pdf

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Francis Glassborow

unread,
Jun 16, 2006, 2:52:53 PM6/16/06
to
In article <Xns97E4A9B1CFB...@194.125.133.14>, Frederick
Gotham <fgot...@SPAM.com> writes

>
>About a year or two ago, I started searching the internet for some code
>which implements a "typeof" operator, and I came up with a few template
>near-solutions.
>
>There are quite a few inherent problems with C++ which can be solved with
>templates, and once such a template has been devised (e.g. boost's
>"implict_cast"), people tend to pipe down about it.
>
>Today, I again found myself wanting a "typeof" operator, and I find it
>ludicrous that the language doesn't provide such basic functionality.
>
>A "typeof" operator should be very like the "sizeof" operator, in that it
>doesn't evaluate the expression.
>
>Two things which I think should be a concrete feature in the language
>(rather than achieved with template cleverness) are:
>
> typeof
> implicit_cast
>
>
>Are there intentions to add these to the language?
>
>
>
>
Before making such over the top statements why don't you just have a
look at the list od papers proposing changes for the next version of
C++.

In fact typeof is not straight forward in a language where things such
as pointers and references can have distinct dynamic and static types.
But just have a look (Google for SC22 WG21 and follow the obvious link)


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Greg Herlihy

unread,
Jun 16, 2006, 4:28:57 PM6/16/06
to

Frederick Gotham wrote:
> About a year or two ago, I started searching the internet for some code
> which implements a "typeof" operator, and I came up with a few template
> near-solutions.
>
> There are quite a few inherent problems with C++ which can be solved with
> templates, and once such a template has been devised (e.g. boost's
> "implict_cast"), people tend to pipe down about it.
>
> Today, I again found myself wanting a "typeof" operator, and I find it
> ludicrous that the language doesn't provide such basic functionality.
>
> A "typeof" operator should be very like the "sizeof" operator, in that it
> doesn't evaluate the expression.
>
> Two things which I think should be a concrete feature in the language
> (rather than achieved with template cleverness) are:
>
> typeof
> implicit_cast

Isn''t an implicit_cast operator an oxymoron? And furthermore, doesn't
static_cast have the explicit-cast-where-none-is-needed market cornered
already?

In fact, because an implicit conversion - by definition - occurs
without the presence of an explicit cast operator, any and every use of
an implicit_cast operator in a program would, it seems to me, be
entirely gratuitous. So how can an operator that by all appearances
would do absolutely nothing and would never be needed - still be
considered a fundamental feature that is somehow "missing" from the
language?

Greg

David Abrahams

unread,
Jun 17, 2006, 10:21:14 AM6/17/06
to
"Greg Herlihy" <gre...@pacbell.net> writes:

> Isn''t an implicit_cast operator an oxymoron?

No.

> And furthermore, doesn't static_cast have the
> explicit-cast-where-none-is-needed market cornered already?

No, static_cast is way more powerful -- and dangerous -- than that.
It's a good idea to limit casts used to the least powerful and
dangerous ones possible, which is why we use C++-style casts instead
of C-style.

> In fact, because an implicit conversion - by definition - occurs
> without the presence of an explicit cast operator, any and every use of
> an implicit_cast operator in a program would, it seems to me, be
> entirely gratuitous.


template <class T> T f(T x) { return x*x; }

long x = f(1 << 15); // T is int
long x = f( implicit_cast<long>(1 << 15) ); // T is long


There are other reasons to want this operator. Explicit construction
of temporary built-ins actually amounts to a cast.

class Foo {};

Foo x = Foo("hello"); // error, as desired
int x = int("hello"); // no error

So in generic code if you want to produce a temporary object of type
"T" and T could turn out to be a builting, implicit_cast might be a
better choice than explicit construction.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Frederick Gotham

unread,
Jun 17, 2006, 3:05:58 PM6/17/06
to
Greg Herlihy posted:


> In fact, because an implicit conversion - by definition - occurs
> without the presence of an explicit cast operator, any and every use
> of an implicit_cast operator in a program would, it seems to me, be
> entirely gratuitous. So how can an operator that by all appearances
> would do absolutely nothing and would never be needed - still be
> considered a fundamental feature that is somehow "missing" from the
> language?


David gave some very good examples. Another more basic one:


void ArbitraryFunc( signed char );
void ArbitraryFunc( unsigned char );
void ArbitraryFunc( char );


int main()
{
ArbitraryFunc( implicit_cast<unsigned char>( 56 ) );
}

"static_cast" is more powerful than "implict_cast", e.g.:


void *p_v;

char *p_c;


p_c = static_cast<char*>(p_v); /* No problem */

p_c = implicit_cast<char*>(p_v); /* Type mismatch */


--

Frederick Gotham

David Abrahams

unread,
Jun 18, 2006, 1:28:11 PM6/18/06
to
Francis Glassborow <fra...@robinton.demon.co.uk> writes:

> In fact typeof is not straight forward in a language where things
> such as pointers and references can have distinct dynamic and static
> types.

Yes it is. Unlike typeid, typeof is supposed to operate entirely at
compile-time, so dynamic type information is irrelevant.

Covering all the use cases for a compile-time typeof, however, is
nontrivial, which is why we have decltype.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---

Gene Bushuyev

unread,
Jun 18, 2006, 1:31:09 PM6/18/06
to
"David Abrahams" <da...@boost-consulting.com> wrote in message
news:u1wto5...@boost-consulting.com...

> "Greg Herlihy" <gre...@pacbell.net> writes:
>
>> Isn''t an implicit_cast operator an oxymoron?
>
> No.

It is an oxymoron indeed. A construct (cast) cannot be implicit while being used
explicitly, can it?
I would suggest a better name for the feature, something like
standard_conversion<>.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
teamwork, (n, circa 1828) 1. euphemism for mediocrity. (see also, team-player)

Alberto Ganesh Barbati

unread,
Jun 18, 2006, 1:32:08 PM6/18/06
to
David Abrahams ha scritto:

> class Foo {};
>
> Foo x = Foo("hello"); // error, as desired
> int x = int("hello"); // no error
>

In fact I always wondered why function style casts are defined that way.
In practice 5.2.3 says that

int(expr)

is equivalent to

(int)(expr)

According to the least astonishing principle, it should have been
equivalent to

static_cast<int>(expr)

instead... With this definition, int("hello") would be ill-formed. Do
you know the rationale why the standard has defined function-style casts
that way? Is there something we could do to fix the situation (in case
there someone else that agree with me that the current definition is
kind of "wrong")? For example that could be achieved by deprecating
(without removing) the reinterpret_cast-ness of the idiom, thus allowing
compiler vendors to issue a warning without breaking existing code.

Ganesh

David Abrahams

unread,
Jun 18, 2006, 5:13:34 PM6/18/06
to
sp...@spamguard.com ("Gene Bushuyev") writes:

> "David Abrahams" <da...@boost-consulting.com> wrote in message
> news:u1wto5...@boost-consulting.com...
>> "Greg Herlihy" <gre...@pacbell.net> writes:
>>
>>> Isn''t an implicit_cast operator an oxymoron?
>>
>> No.
>
> It is an oxymoron indeed. A construct (cast) cannot be implicit
> while being used explicitly, can it?

implicit_cast will only perform conversions that can also be made
implicitly.

> I would suggest a better name for the feature, something like
> standard_conversion<>.

That's not better at all. implicit_cast can perform any "nonstandard"
user-defined conversions that can also happen implicitly.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---

David Abrahams

unread,
Jun 18, 2006, 5:14:00 PM6/18/06
to
Alberto...@libero.it (Alberto Ganesh Barbati) writes:


> Do you know the rationale why the standard has defined
> function-style casts that way?

No; I'd check D&E if I was curious.

> Is there something we could do to fix
> the situation (in case there someone else that agree with me that
> the current definition is kind of "wrong")?

You know, bring proposals to the standard committee.

> For example that could
> be achieved by deprecating (without removing) the
> reinterpret_cast-ness of the idiom, thus allowing compiler vendors
> to issue a warning without breaking existing code.

Compiler vendors are allowed to issue any warnings they like without
deprecations.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---

Greg Herlihy

unread,
Jun 19, 2006, 11:33:37 AM6/19/06
to
David Abrahams wrote:
> "Greg Herlihy" <gre...@pacbell.net> writes:
>
> > Isn''t an implicit_cast operator an oxymoron?
>
> No.
>
> > And furthermore, doesn't static_cast have the
> > explicit-cast-where-none-is-needed market cornered already?
>
> No, static_cast is way more powerful -- and dangerous -- than that.
> It's a good idea to limit casts used to the least powerful and
> dangerous ones possible, which is why we use C++-style casts instead
> of C-style.
>
> > In fact, because an implicit conversion - by definition - occurs
> > without the presence of an explicit cast operator, any and every use of
> > an implicit_cast operator in a program would, it seems to me, be
> > entirely gratuitous.
>
>
> template <class T> T f(T x) { return x*x; }
>
> long x = f(1 << 15); // T is int
> long x = f( implicit_cast<long>(1 << 15) ); // T is long

The problem with the implicit_cast in the call to f() above is that it
obscures the programmer's intent. My first reaction upon seeing the
cast is that it is unneeded wherever (1 << 15) can be represented by an
int (which is nearly everyone). Furthermore, the word "implicit" only
reinforces my conclusion. The presence of an "implicit_cast" operator
suggests to me that this exact conversion would occur without needing
an explicit operator - so there should not be any harm in removing it.

Of course there would be harm in removing the cast, because the purpose
of the cast is to specify not the parameter type - but actually to
specify the function's return type. In other words, f() must be a
function template of a certain form - but there is nothing in the call
to f() by itself that suggests that f is a template function.

Furthermore the language already offers a way to call a template
function explicitly - and to do so without resorting to such a
roundabout technique:

long x = f<long>(1 << 15);

In this case, I would not be tempted to remove the "long" because its
presence communicates its purpose. Whereas the purpose (if any) of the
cast in the original example cannot be determined without also knowing
the declaration of f().

A static_cast would have worked just as well (or just as poorly) as the
implicit_cast above. In fact an implicit_cast would not be any better
than a static_cast in general - since longs convert to ints implicitly.
And presumably it is precisely those types of lossy conversions that
this new cast operator not be performing. Because I think that the
unstated motivation behind devising a new cast operator is to provide
greater safety- but unfortunately implicit casts are not safe; so
linking a new cast operator to implicit casts obscures the potential
benefit of such an operator - in much the same way that using the
implicit_cast above obscures the reason for using it in the first
place.

In short, the language doesn't need an implicit_cast operator. If C++
needs a new cast operator at all then it needs a "safe_cast" operator.
A safe_cast would be just that - a cast between types that will not
lose information. Off the top of my head, a safe_cast could perform a
conversion from:

Any type to the same type
An integral type to another integral of equal or greater range
A class type to one of its (non-virtual) base class types
A floating point value to another floating point type of equal or
greater precision

There are probably some that I missed. In other words a "safe_cast"
would perform "worry-free" conversions. And by doing so, a safe_cast
that would be a kind of cast operator which the language does not
currently provide.

Greg

David Abrahams

unread,
Jun 19, 2006, 12:18:17 PM6/19/06
to
"Greg Herlihy" <gre...@pacbell.net> writes:

> David Abrahams wrote:
>> "Greg Herlihy" <gre...@pacbell.net> writes:
>>
>> > Isn''t an implicit_cast operator an oxymoron?
>>
>> No.
>>
>> > And furthermore, doesn't static_cast have the
>> > explicit-cast-where-none-is-needed market cornered already?
>>
>> No, static_cast is way more powerful -- and dangerous -- than that.
>> It's a good idea to limit casts used to the least powerful and
>> dangerous ones possible, which is why we use C++-style casts instead
>> of C-style.
>>
>> > In fact, because an implicit conversion - by definition - occurs
>> > without the presence of an explicit cast operator, any and every use of
>> > an implicit_cast operator in a program would, it seems to me, be
>> > entirely gratuitous.
>>
>>
>> template <class T> T f(T x) { return x*x; }
>>
>> long x = f(1 << 15); // T is int
>> long x = f( implicit_cast<long>(1 << 15) ); // T is long
>
> The problem with the implicit_cast in the call to f() above is that it
> obscures the programmer's intent.

Okay, I'll bite...

> My first reaction upon seeing the cast is that it is unneeded
> wherever (1 << 15) can be represented by an int (which is nearly
> everyone).

Assume the author is trying to write portable code. Or assume there's
a short in use here. I was not trying to write the perfect example
that counters all arguments; I was just trying to show, as simply as
possible, that it's not gratuitous.

Here's another. Yes, such classes do exist in well-written code.

struct X
{
template <class T>
operator T() const;
};

f( implicit_cast<long>(x) );


Oh, here's another.

// Handle iterators with proxy references correctly
f( implicit_cast<std::iterator_traits<It>::value_type>(*it) );

> Furthermore, the word "implicit" only reinforces my conclusion. The
> presence of an "implicit_cast" operator suggests to me that this
> exact conversion would occur without needing an explicit operator -
> so there should not be any harm in removing it.

Yes, it's one of those things for which there ought to be a better
name, but nobody's yet found one.

force_implicitly_available_conversion_to<T>(x)
conversion_that_occurs_implicitly_in_some_contexts_to<T>(x)

??

> Of course there would be harm in removing the cast,

Thank you. Do you now agree that it isn't gratuitous?

> because the purpose of the cast is to specify not the parameter type
> - but actually to specify the function's return type. In other
> words, f() must be a function template of a certain form - but there
> is nothing in the call to f() by itself that suggests that f is a
> template function.

Can you not stretch your imagination to cover a case where
it's important to specify the parameter type?

> Furthermore the language already offers a way to call a template
> function explicitly - and to do so without resorting to such a
> roundabout technique:
>
> long x = f<long>(1 << 15);


Fine.

void f(int y)
{
long x = implicit_cast<long>(y) * y;
...
}

> A static_cast would have worked just as well (or just as poorly) as
> the implicit_cast above. In fact an implicit_cast would not be any
> better than a static_cast in general - since longs convert to ints
> implicitly.

Not in general; only in the case of converting inter-convertible
types. But most implicit conversions are not of that nature. Most
people try not to promulgate the mistakes of 'C', and most
user-defined numeric types such as boost::rational are better-behaved.

> And presumably it is precisely those types of lossy conversions that
> this new cast operator not be performing. Because I think that the
> unstated motivation behind devising a new cast operator is to
> provide greater safety-

Yes.

> but unfortunately implicit casts are not safe;

True; not all implicit conversions are safe. implicit_cast is still
safer than static_cast because static_cast is a superset of implicit
cast. So implicit_cast allows fewer unsafe conversions.

> so linking a new cast operator to implicit casts obscures the
> potential benefit of such an operator - in much the same way that
> using the implicit_cast above obscures the reason for using it in
> the first place.

The reason for using it in the first place above was to show that
sometimes it's not gratuitous :)

> In short, the language doesn't need an implicit_cast operator. If
> C++ needs a new cast operator at all then it needs a "safe_cast"
> operator. A safe_cast would be just that - a cast between types
> that will not lose information. Off the top of my head, a safe_cast
> could perform a conversion from:
>
> Any type to the same type
> An integral type to another integral of equal or greater range
> A class type to one of its (non-virtual) base class types

That doesn't lose information? Since when? And why only non-virtual bases?

> A floating point value to another floating point type of equal
> or greater precision

What about mantissas?

> There are probably some that I missed. In other words a "safe_cast"
> would perform "worry-free" conversions. And by doing so, a safe_cast
> that would be a kind of cast operator which the language does not
> currently provide.

I think that would be wonderful to have, but of course such an
operator is not possible by itself without ruling out many safe
conversions. For example, your rules wouldn't allow
int->boost::rational<int>, which is non-lossy, and any user-defined
int->type can define a lossy implicit conversion, so without requiring
int->users to define some external traits that tell the system which
conversions are lossy, nobody can be satisfied.

Anyway, lossiness is really the wrong criterion. Plenty of
conversions are lossy but safe, e.g. the one that happens in

if ( some_shared_ptr ) { ... }

Testing that the cast can be performed implicitly is really the best
way we have of guessing whether a cast will be safe. As an
alternative to static_cast, implicit_cast helps.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---

Francis Glassborow

unread,
Jun 20, 2006, 7:31:16 AM6/20/06
to
In article <u1wtlt...@boost-consulting.com>, David Abrahams
<da...@boost-consulting.com> writes

>Testing that the cast can be performed implicitly is really the best
>way we have of guessing whether a cast will be safe. As an
>alternative to static_cast, implicit_cast helps.


I wonder if we could restrict implicit_cast so that it will never apply
a narrowing conversion or would that destroy its use?

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---

David Abrahams

unread,
Jun 20, 2006, 10:30:55 AM6/20/06
to
fra...@robinton.demon.co.uk (Francis Glassborow) writes:

> In article <u1wtlt...@boost-consulting.com>, David Abrahams
> <da...@boost-consulting.com> writes
>>Testing that the cast can be performed implicitly is really the best
>>way we have of guessing whether a cast will be safe. As an
>>alternative to static_cast, implicit_cast helps.
>
>
> I wonder if we could restrict implicit_cast so that it will never
> apply a narrowing conversion or would that destroy its use?

No, because the user can always define such a narrowing conversion of
his own (e.g. rational=>int). We could, however, restrict it so that
no built-in narrowing conversions occur, which should account for most
such conversions... except that you'd still want to allow Derived* =>
Base*, which is narrowing (at least, it's lossy). And if you could
work out all those details, what would you call such a cast and how
would you make it teachable?

Sometimes a simple design that does less is better than a more capable
design with lots of special cases.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

---

Alberto Ganesh Barbati

unread,
Jun 20, 2006, 11:09:47 AM6/20/06
to
David Abrahams ha scritto:

> Alberto...@libero.it (Alberto Ganesh Barbati) writes:
>
>> Is there something we could do to fix
>> the situation (in case there someone else that agree with me that
>> the current definition is kind of "wrong")?
>
> You know, bring proposals to the standard committee.

The only thing that comes to my mind is to introduce #pragma notations
as C does, for example:

#pragma STDCPP FUNCTIONAL_CAST_IS_STATIC [on/off]

Such approach might also be considered as a general framework for
enforcing minor (but possibly breaking) behaviour changes, such as
disallowing the deprecated string literal to non-const char* conversion.

>> For example that could
>> be achieved by deprecating (without removing) the
>> reinterpret_cast-ness of the idiom, thus allowing compiler vendors
>> to issue a warning without breaking existing code.
>
> Compiler vendors are allowed to issue any warnings they like without
> deprecations.
>

Yes, but sometimes an official encouragement can be useful ;)

Ganesh

Krzysztof Zelechowski

unread,
Jun 20, 2006, 5:46:30 PM6/20/06
to

Uzytkownik "Greg Herlihy" <gre...@pacbell.net> napisal w wiadomosci
news:1150485390....@y41g2000cwy.googlegroups.com...

> Isn''t an implicit_cast operator an oxymoron? And furthermore, doesn't
> static_cast have the explicit-cast-where-none-is-needed market cornered
> already?
>
> In fact, because an implicit conversion - by definition - occurs
> without the presence of an explicit cast operator, any and every use of
> an implicit_cast operator in a program would, it seems to me, be
> entirely gratuitous. So how can an operator that by all appearances
> would do absolutely nothing and would never be needed - still be
> considered a fundamental feature that is somehow "missing" from the
> language?
>
> Greg

Try this:

class B {};
class D: public B {};
extern B g_val; // somewhere deep in a header file

void foo_D(__typefix(D *) void *);
void bar(void *, void (*)(void *));
bar(&g_val, foo_D); // Run-time error.

D *a_p = g_val; // Ill-formed, but such constructs cannot be used in
expressions.
bar(a_p, foo_D); // Never executed.

bar(static_cast<D *> (&g_val), foo_D); // Run-time error.
bar(implicit_cast<D *>(&g_val), foo_D); // Ill-formed, never executed.

See? You have just spared some $$ on code maintenance and technical
support.
Chris

Greg Herlihy

unread,
Jun 21, 2006, 4:06:45 AM6/21/06
to

Yes, but the pertinent question is whether this bug was fixed with two
changes (removing the static_cast operator and adding the implicit_cast
operator) or with just one? Let's test each change in isolation to find
the answer.

First, removing the static_cast:

bar( &g_val, foo_D); // ill-formed, never compiled

After making this change, the bug is fixed. No subsequent change is
necessary. Granted, the timely appearance of the implicit_cast at this
point may create the impression that it plays some useful role in
fixing the bug. But to assign the implicit_cast any more credit for the
fix than a comment would have merited is to overstate its role.

In contrast adding just the implicit_cast operator:

bar(implicit_cast<D *>(static_cast<D*>(&g_val)), foo_D); // error

does not solve the problem.

So the conclusion to be drawn is that not only was the implicit_cast
not needed to solve this particular problem, but that the implicit_cast
operator is in fact incapable of fixing this kind of problem in the
first place.

Greg

kanze

unread,
Jun 21, 2006, 11:55:24 AM6/21/06
to
Alberto Ganesh Barbati wrote:
> David Abrahams ha scritto:
> > Alberto...@libero.it (Alberto Ganesh Barbati) writes:

> >> Is there something we could do to fix the situation (in
> >> case there someone else that agree with me that the current
> >> definition is kind of "wrong")?

> > You know, bring proposals to the standard committee.

> The only thing that comes to my mind is to introduce #pragma
> notations as C does, for example:

> #pragma STDCPP FUNCTIONAL_CAST_IS_STATIC [on/off]

> Such approach might also be considered as a general framework
> for enforcing minor (but possibly breaking) behaviour changes,
> such as disallowing the deprecated string literal to non-const
> char* conversion.

> >> For example that could be achieved by deprecating (without
> >> removing) the reinterpret_cast-ness of the idiom, thus
> >> allowing compiler vendors to issue a warning without
> >> breaking existing code.

> > Compiler vendors are allowed to issue any warnings they like
> > without deprecations.

> Yes, but sometimes an official encouragement can be useful ;)

If you want to fiddle with the definitions of casts, I'd suggest
extending C style casts to allow them to be used for everything
the functional notation does, i.e. '(MyClass)( x, y, z )', etc.,
then deprecating the functional style casts completely. Once
people start using the parentheses around the type
systematically, and something like:

std::vector< int > v( (std::istream_iterator< int >)( fIn ),
(std::istream_iterator< int >)() ) ;

is the only non-deprecated way to write it, we've eliminated one
embaressing surprise that newbies (and all to often not so
newbies) encounter.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

kanze

unread,
Jun 21, 2006, 12:26:21 PM6/21/06
to
David Abrahams wrote:
> Alberto...@libero.it (Alberto Ganesh Barbati) writes:

> > Do you know the rationale why the standard has defined
> > function-style casts that way?

> No; I'd check D&E if I was curious.

Even without checking D&E: function-style casts existed long
before the new cast syntax was invented.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Greg Herlihy

unread,
Jun 21, 2006, 12:26:14 PM6/21/06
to
David Abrahams wrote:
> fra...@robinton.demon.co.uk (Francis Glassborow) writes:
>
> > In article <u1wtlt...@boost-consulting.com>, David Abrahams
> > <da...@boost-consulting.com> writes
> >>Testing that the cast can be performed implicitly is really the best
> >>way we have of guessing whether a cast will be safe. As an
> >>alternative to static_cast, implicit_cast helps.
> >
> >
> > I wonder if we could restrict implicit_cast so that it will never
> > apply a narrowing conversion or would that destroy its use?
>
> No, because the user can always define such a narrowing conversion of
> his own (e.g. rational=>int). We could, however, restrict it so that
> no built-in narrowing conversions occur, which should account for most
> such conversions... except that you'd still want to allow Derived* =>
> Base*, which is narrowing (at least, it's lossy). And if you could
> work out all those details, what would you call such a cast and how
> would you make it teachable?
>
> Sometimes a simple design that does less is better than a more capable
> design with lots of special cases.

The test for a "safe" conversion would be extremely simple - and has
nothing to do with issues of narrowing or lossiness (at least not
directly) - because the only question is one of definedness. In other
words: converting a value of type A to a value of type B is a "safe"
conversion if and only if the Standard has defined a value of B for
every value defined in A.

In other words, the Standard must define a one-to-one correspondence
between A object values and their converted B object values. If that is
not the case - if there are defined values in A for which only
implemention-defined or undefined converted values exist in B, then the
cast would not be considered "safe".

And this test is easy to apply in practice. For example, an int to bool
conversion would be considered safe because - although the conversion
loses information - the converted bool value is defined for any int
value. On the other hand, a narrowing integer conversion would be
unsafe - because some of the converted values are implementation
defined. Converting a base to a derived type would also not be
considered safe - since there are values of base that convert to no
defined value in derived. Converting in the opposite direction - from
derived to base on the other hand - would be a safe conversion, since
there is a defined base value for every defined value of derived.

In essence a C++ programmer should never perform a (non-dynamic)
conversion to find out what the converted value will be - on the
contrary, such conversions should be performed only when the converted
value is not in any doubt.

Greg

kuy...@wizard.net

unread,
Jun 21, 2006, 2:45:53 PM6/21/06
to
Greg Herlihy wrote:
.
> In other words, the Standard must define a one-to-one correspondence
> between A object values and their converted B object values. If that is
> not the case - if there are defined values in A for which only
> implemention-defined or undefined converted values exist in B, then the
> cast would not be considered "safe".

There are many possible definitions of "safe conversion"; that's just
one of them. The consequences of conversion between standard-defined
types include undefined behavior, unspecified behavior, unspecified
values, wrap-around, and possible loss of precision. Any of those
problems could be perfectly acceptable in the right context. Even
undefined behavior can be acceptable, if it is defined by something
other than the standard, and the code is not intended for use outside
the validity of that other definition. Even the mildest problem, loss
of precision (from, for instance, long double -> double), can be
unacceptable in some contexts. Wrap-around is certainly dangerous, at
least when unexpected, yet it's a one-to-one conversion, as you've
specified, when converting an unsigned type to a sufficiently large
signed type.

The strictest definition of a safe conversion that I can think of is
that a conversion is safe if inverting the conversion is guaranteed to
produce a value that compares equal to the original value.

> ...For example, an int to bool


> conversion would be considered safe because - although the conversion
> loses information - the converted bool value is defined for any int
> value.

You specified "one-to-one" correspondence. The int->bool conversion is
many-to-one. A definition of "safe" conversions that includes int->bool
is of limited use to me; in most contexts, I need a much stricter
definition.

john...@yahoo.com

unread,
Jun 21, 2006, 2:46:19 PM6/21/06
to
Greg Herlihy wrote:

> On the other hand, a narrowing integer conversion would be
> unsafe - because some of the converted values are implementation
> defined.

Unless the destination type is unsigned (4.7/2). So converting long to
unsigned char would be "safe."

Francis Glassborow

unread,
Jun 21, 2006, 3:07:15 PM6/21/06
to
In article <1150896508.4...@c74g2000cwc.googlegroups.com>, Greg
Herlihy <gre...@pacbell.net> writes

>In other words, the Standard must define a one-to-one correspondence
>between A object values and their converted B object values. If that is
>not the case - if there are defined values in A for which only
>implemention-defined or undefined converted values exist in B, then the
>cast would not be considered "safe".

Did you mean one-one? Because in that case narrowing conversions are
out.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

---

Falk Tannhäuser

unread,
Jun 23, 2006, 4:09:27 PM6/23/06
to
Alberto Ganesh Barbati wrote:
> In fact I always wondered why function style casts are defined that way.
> In practice 5.2.3 says that
>
> int(expr)
>
> is equivalent to
>
> (int)(expr)
>
> According to the least astonishing principle, it should have been
> equivalent to
>
> static_cast<int>(expr)
>
> instead... With this definition, int("hello") would be ill-formed. Do
> you know the rationale why the standard has defined function-style casts
> that way?

Certainly historical reasons - function style casts (as a means of
generalizing conversion constructor calls) appeared in C++ prior
to new-style casts.

Falk

0 new messages