By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,446 Members | 3,019 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,446 IT Pros & Developers. It's quick & easy.

conversion syntax

P: n/a
REH
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:

unsigned long x = unsigned long(y);

REH
Oct 8 '08 #1
Share this Question
Share on Google+
21 Replies


P: n/a
REH wrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:

unsigned long x = unsigned long(y);
If I'm not mistaken, if you want to make a C-style cast to a type
which consists of several keywords, you have to enclose them in
parentheses. That is:

unsigned long x = (unsigned long)(y);

Of course the recommended way in C++ is to use a C++ style cast:

unsigned long x = static_cast<unsigned long>(y);
Oct 8 '08 #2

P: n/a
REH
On Oct 8, 10:36*am, Juha Nieminen <nos...@thanks.invalidwrote:
REH wrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);

* If I'm not mistaken, if you want to make a C-style cast to a type
which consists of several keywords, you have to enclose them in
parentheses. That is:

* * unsigned long x = (unsigned long)(y);

* Of course the recommended way in C++ is to use a C++ style cast:

* * unsigned long x = static_cast<unsigned long>(y);
Thanks. I know. I was just wondering if the constructor style was
legal.

Oct 8 '08 #3

P: n/a
On Oct 8, 3:36*pm, Juha Nieminen <nos...@thanks.invalidwrote:
REH wrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);

* If I'm not mistaken, if you want to make a C-style cast to a type
which consists of several keywords, you have to enclose them in
parentheses. That is:

* * unsigned long x = (unsigned long)(y);

* Of course the recommended way in C++ is to use a C++ style cast:

* * unsigned long x = static_cast<unsigned long>(y);
The original question, IMO, involved C++ functional style cast, rather
than C-style cast.

--
Max
Oct 8 '08 #4

P: n/a
REH wrote:
Thanks. I know. I was just wondering if the constructor style was
legal.
Well, it is legal as long as your type consists of one single symbol.
For example this will always be legal:

template<typename T>
void foo()
{
T x = T(y);
}

This even if you call it like foo<unsigned long>(). That's because 'T'
is just one symbol.

Rather curiously, this is legal too:

template<typename T>
void foo()
{
T x = (T)y;
}

And this even if T is a class (with a constructor which takes a
parameter of the type of 'y').

Oct 8 '08 #5

P: n/a
REH <sp******@stny.rr.comwrites:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:

unsigned long x = unsigned long(y);
Well, C++ syntax is rather complex. It's understandable it's hard to
read, to understand and therefore to implement correctly. I don't
know what is specified there.

Since you observe that's a hard dark corner with diverging
implementation, my advice would be to avoid it. Or to use parentheses.

typedef unsigned long ulong;
ulong x = ulong(y);

or:

unsigned long x = (unsigned long)(y);
--
__Pascal Bourguignon__
Oct 8 '08 #6

P: n/a
REH
On Oct 8, 10:47*am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
REH <spamj...@stny.rr.comwrites:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);

Well, C++ syntax is rather complex. *It's understandable it's hard to
read, to understand and therefore to implement correctly. * I don't
know what is specified there.

Since you observe that's a hard dark corner with diverging
implementation, my advice would be to avoid it. *Or to use parentheses.

* * typedef unsigned long ulong;
* * ulong x = ulong(y);

or:

* * unsigned long x = (unsigned long)(y);

--
__Pascal Bourguignon__
Sigh. Yes, I know that. My question is simply: is the syntax legal or
not?

REH
Oct 8 '08 #7

P: n/a
Maxim Yegorushkin <ma***************@gmail.comwrites:
On Oct 8, 3:36*pm, Juha Nieminen <nos...@thanks.invalidwrote:
>REH wrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);

* If I'm not mistaken, if you want to make a C-style cast to a type
which consists of several keywords, you have to enclose them in
parentheses. That is:

* * unsigned long x = (unsigned long)(y);

* Of course the recommended way in C++ is to use a C++ style cast:

* * unsigned long x = static_cast<unsigned long>(y);

The original question, IMO, involved C++ functional style cast, rather
than C-style cast.
Which funnily, is not decided when you write:

unsigned long x = (unsigned long)(y);

The compiler could as well decide to parse it as a C cast as a C++
functional style cast. I think it'll be my favorite way to write it,
let the compiler deal with it as it wants :-)

--
__Pascal Bourguignon__
Oct 8 '08 #8

P: n/a
REH
On Oct 8, 11:29*am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
Maxim Yegorushkin <maxim.yegorush...@gmail.comwrites:
On Oct 8, 3:36*pm, Juha Nieminen <nos...@thanks.invalidwrote:
REH wrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);
* If I'm not mistaken, if you want to make a C-style cast to a type
which consists of several keywords, you have to enclose them in
parentheses. That is:
* * unsigned long x = (unsigned long)(y);
* Of course the recommended way in C++ is to use a C++ style cast:
* * unsigned long x = static_cast<unsigned long>(y);
The original question, IMO, involved C++ functional style cast, rather
than C-style cast.

Which funnily, is not decided when you write:

* * unsigned long x = (unsigned long)(y);

The compiler could as well decide to parse it as a C cast as a C++
functional style cast. * I think it'll be my favorite way to write it,
let the compiler deal with it as it wants :-)
Maxim understands that it was a question about syntax, not semantics.

REH
Oct 8 '08 #9

P: n/a
REH
On Oct 8, 10:29*am, REH <spamj...@stny.rr.comwrote:
It it permissible to use the constructor style cast with primitives
such as "unsigned long"? One of my compilers accepts this syntax, the
other does not. The failing one chokes on the fact that the type is
not a single identifier or keyword. Which one is correct? For example:

unsigned long x = unsigned long(y);
OK, if I read the sections in the standard defining "simple-type-
specifier" and "postfix-expression" correctly, the syntax is not
valid.

REH
Oct 8 '08 #10

P: n/a
REH
On Oct 8, 11:29*am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
Which funnily, is not decided when you write:

* * unsigned long x = (unsigned long)(y);

The compiler could as well decide to parse it as a C cast as a C++
functional style cast. * I think it'll be my favorite way to write it,
let the compiler deal with it as it wants :-)
It don't matter how you write it, when there is a valid conversion
from T to U, these are all equivalent:

U(T);
(U) T;
static_cast<U>(T);
REH
Oct 8 '08 #11

P: n/a
On 2008-10-08 12:38:20 -0400, REH <sp******@stny.rr.comsaid:
On Oct 8, 11:29Â*am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
>Which funnily, is not decided when you write:

Â* Â* unsigned long x = (unsigned long)(y);

The compiler could as well decide to parse it as a C cast as a C++
functional style cast. Â* I think it'll be my favorite way to write it,
let the compiler deal with it as it wants :-)

It don't matter how you write it, when there is a valid conversion
from T to U, these are all equivalent:

U(T);
(U) T;
static_cast<U>(T);

It does matter what you write. The second also applies to situations
where the others don't, and some people think that this leads to errors.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 8 '08 #12

P: n/a
REH
On Oct 8, 12:41*pm, Pete Becker <p...@versatilecoding.comwrote:
On 2008-10-08 12:38:20 -0400, REH <spamj...@stny.rr.comsaid:
On Oct 8, 11:29*am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
Which funnily, is not decided when you write:
* * unsigned long x = (unsigned long)(y);
The compiler could as well decide to parse it as a C cast as a C++
functional style cast. * I think it'll be my favorite way to write it,
let the compiler deal with it as it wants :-)
It don't matter how you write it, when there is a valid conversion
from T to U, these are all equivalent:
U(T);
(U) T;
static_cast<U>(T);

It does matter what you write. The second also applies to situations
where the others don't, and some people think that this leads to errors.
I use "doesn't matter" to mean when the three versions valid, change
from one to the other will not produce a different meaning. I agree
that c-style casts can be dangerous.

REH
Oct 8 '08 #13

P: n/a
On Oct 8, 5:29 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
Maxim Yegorushkin <maxim.yegorush...@gmail.comwrites:
On Oct 8, 3:36 pm, Juha Nieminen <nos...@thanks.invalidwrote:
REH wrote:
It it permissible to use the constructor style cast with
primitives such as "unsigned long"? One of my compilers
accepts this syntax, the other does not. The failing one
chokes on the fact that the type is not a single
identifier or keyword. Which one is correct? For example:
unsigned long x = unsigned long(y);
If I'm not mistaken, if you want to make a C-style cast to
a type which consists of several keywords, you have to
enclose them in parentheses.
Not a C-style cast; an "explicit type conversion (functional
notation)". The sytax for this requires either a
simple-type-specifier or a typename-specifier to the left of the
parentheses. A simple-type-specifier can be either a single
token, or a qualified type name, e.g. X::Y::Z. It cannot be the
name of a type which requires several tokens to specify, so the
answer to his question is no.
That is:
unsigned long x = (unsigned long)(y);
Of course the recommended way in C++ is to use a C++ style cast:
unsigned long x = static_cast<unsigned long>(y);
Recommended by whom? I've never seen code which didn't use the
functional notation for type conversion; if the number of
arguments is anything other than one, it's the only type of type
conversion which works. I'd strongly recommend using the new
cast syntax for pointer and reference casts, but for the others,
I generally use either a C style cast or the functional
notation.
The original question, IMO, involved C++ functional style
cast, rather than C-style cast.
Which funnily, is not decided when you write:
unsigned long x = (unsigned long)(y);
Yes it is. That's an "explicit type conversion (cast
notation)"---a C style cast. The functional notation has a
particularity that the others don't have: you can convert
nothing, or more than one thing:-). (And yes, calling it a
conversion is a bit strange, but that's what the standard does.)
So given a user defined type A:

A() explicit type conversion (functional notation)
(A)() illegal
static_cast< A >() illegal

A( x ) explicit type conversion (functional notation)
(A)( x ) explicit type conversion (cast notation)
static_cast< A >( x ) static_cast

A( x, y ) explicit type conversion (functional notation)
(A)( x, y ) illegal
static_cast< A >( x, y ) illegal

In each group of three, all of the legal syntaxes have exactly
the same semantics (and note that A(x) doesn't necessarily call
the constructor of A---it can also call a user defined coversion
operator of x).
The compiler could as well decide to parse it as a C cast as a
C++ functional style cast. I think it'll be my favorite way
to write it, let the compiler deal with it as it wants :-)
Personally, I think it would have been clearer if the cast
notation had been extended to allow multiple arguments, and the
function style casts hadn't been introduced. That would have
eliminated a lot of ambiguities. But it's too late for that
now.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Oct 8 '08 #14

P: n/a
REH
On Oct 8, 12:51*pm, James Kanze <james.ka...@gmail.comwrote:
Not a C-style cast; an "explicit type conversion (functional
notation)". *The sytax for this requires either a
simple-type-specifier or a typename-specifier to the left of the
parentheses. *A simple-type-specifier can be either a single
token, or a qualified type name, e.g. X::Y::Z. *It cannot be the
name of a type which requires several tokens to specify, so the
answer to his question is no.
Thank you, Mr. Kanze.

REH
Oct 8 '08 #15

P: n/a
James Kanze wrote:
>>> unsigned long x = (unsigned long)(y);
>>> Of course the recommended way in C++ is to use a C++ style cast:
>>> unsigned long x = static_cast<unsigned long>(y);

Recommended by whom?
By people who think that converting between incompatible types (in
other words, reinterpret-casting) when that's not your intention is a
bad idea, and that it's better to use the casting which will make the
compiler complain.

The problem with the C-style cast is that it converts almost anything
to almost anything else, which is seldom what you want to do. Usually
you only want to cast between compatible types.
Oct 8 '08 #16

P: n/a
In article <f9**************@read4.inet.fi>,
Juha Nieminen <no****@thanks.invalidwrote:
[...]
The problem with the C-style cast is that it converts almost anything
to almost anything else, which is seldom what you want to do. Usually
you only want to cast between compatible types.
And sadly, C++-style functional casts have this same danger.
Oct 8 '08 #17

P: n/a
On Oct 8, 8:41*pm, Juha Nieminen <nos...@thanks.invalidwrote:
James Kanze wrote:
>>* * unsigned long x = (unsigned long)(y);
>>* Of course the recommended way in C++ is to use a C++ style cast:
>>* * unsigned long x = static_cast<unsigned long>(y);
Recommended by whom?
By people who think that converting between incompatible types
(in other words, reinterpret-casting) when that's not your
intention is a bad idea, and that it's better to use the
casting which will make the compiler complain.
Which is only relevant if there are pointers or references
involved, since all reinterpret_cast's involve pointers and
references.

As I said, I've yet to see any code in which the author avoided
things like "MyClass( x )". Which is a function style cast, and
could be rewritten "static_cast< MyClass >( x )", or things like
"MyClass()" or "MyClass( x, y )", which are function style
classes, and can't be expressed any other way.
The problem with the C-style cast is that it converts almost
anything to almost anything else, which is seldom what you
want to do. Usually you only want to cast between compatible
types.
There is, IMHO, a very definite psychological distinction.
Unless the target type is a reference, a type conversion creates
a new temporary object. In practice, however, with pointer
conversions, we normally think in terms of the pointed to object
(i.e. almost as if it were a reference), and there are several
different conversions possible. So we want a syntax to 1) state
explicitly which conversion we want, and 2) be highly visible
and easy to find, because we are going to access an object in an
unusual way. When converting between numeric types, on the
other hand (e.g. an int to an unsigned long), neither of these
issues are relevant, and we (or I, at least) think of it more
along the same lines as we do things like MyClass( x ). In
other words, a function style cast. Except that if we cannot
name the target type with a single word, we have to add
parentheses around it, which turns it into a C style cast.

In practice, I'll never use a C style cast or a functional style
cast for a pointer or a reference, and I'll almost never use
anything but a functional style cast when explicitly creating a
temporary object of class type (converting to a class type); for
numeric types, I tend to use functional or C style casts, but
I'll occasionally use a static_cast too.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Oct 8 '08 #18

P: n/a
On Oct 8, 9:26*pm, blargg <blargg....@gishpuppy.comwrote:
In article <f97Hk.165$V%4...@read4.inet.fi>,
*Juha Nieminen <nos...@thanks.invalidwrote:
[...]
The problem with the C-style cast is that it converts almost
anything to almost anything else, which is seldom what you
want to do. Usually you only want to cast between compatible
types.
And sadly, C++-style functional casts have this same danger.
Except that the danger is only really present if the target type
is a pointer or a reference, and functional casts can't be used
in such cases.

--
James Kanze (GABI Software) email:ja*********@gmail.com
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
Oct 8 '08 #19

P: n/a
James Kanze wrote:
On Oct 8, 9:26 pm, blargg <blargg....@gishpuppy.comwrote:
>In article <f97Hk.165$V%4...@read4.inet.fi>,
Juha Nieminen <nos...@thanks.invalidwrote:
[...]
>>The problem with the C-style cast is that it converts almost
anything to almost anything else, which is seldom what you
want to do. Usually you only want to cast between compatible
types.
>And sadly, C++-style functional casts have this same danger.

Except that the danger is only really present if the target type
is a pointer or a reference, and functional casts can't be used
in such cases.
I consider this
enum colors { red, green, blue };
colors c = colors(10);
dangerous.

Schobi
Oct 9 '08 #20

P: n/a
On Oct 10, 2:17*am, James Kanze <james.ka...@gmail.comwrote:
On Oct 9, 10:50 am, Hendrik Schober <spamt...@gmx.dewrote:
James Kanze wrote:
On Oct 8, 9:26 pm, blargg <blargg....@gishpuppy.comwrote:
>In article <f97Hk.165$V%4...@read4.inet.fi>,
>*Juha Nieminen <nos...@thanks.invalidwrote:
>[...]
>>The problem with the C-style cast is that it converts
>>almost anything to almost anything else, which is seldom
>>what you want to do. Usually you only want to cast between
>>compatible types.
>And sadly, C++-style functional casts have this same danger.
Except that the danger is only really present if the target
type is a pointer or a reference, and functional casts can't
be used in such cases.
* I consider this
* * enum colors { red, green, blue };
* * colors c = colors(10);
* dangerous.

In the same sense that
* * int i = int( 3.14159 ) ;
is dangerous, yes. *In the case of user defined types, you could
do some runtime checking, but only if you overloaded enough to
avoid the implicit conversions. *Because in the end, if you have
MyClass, with a constructor which takes an int, what is the
different between:
* * int i = int( 3.14159 ) ;
and
* * MyClass c( 3.14159 ) ;

There is, IMHO, a real problem in that many such dangerous
conversions are not only allowed, but happen implicitly. *IIRC,Stroustrup wanted to change this at one point, but the committee
wouldn't follow him. *So we're more or less stuck with them.
More or less, but only more or less. In C++0x we'll get the uniform
initialization syntax and semantics based on { }, and that doesn't
allow narrowing, so

int i1 = int( 3.14159 ) ; // ok (unfortunately)
int i2 = 3.14; // ok (unfortunately)
int i3 = int{3.14}; // error: narrowing
int i3{3.14}; // error: narrowing

colors c1 = colors(10); // ok (unfortunately)
colors c2 = colors{10}; // error: narrowing

Bjarne Stroustrup; http://www.research.att.com/~bs
Oct 12 '08 #21

P: n/a
bjarne wrote:
[...]
More or less, but only more or less. In C++0x we'll get the uniform
initialization syntax and semantics based on { }, and that doesn't
allow narrowing, so

int i1 = int( 3.14159 ) ; // ok (unfortunately)
int i2 = 3.14; // ok (unfortunately)
int i3 = int{3.14}; // error: narrowing
int i3{3.14}; // error: narrowing

colors c1 = colors(10); // ok (unfortunately)
colors c2 = colors{10}; // error: narrowing

Bjarne Stroustrup; http://www.research.att.com/~bs
Sounds good to me.

Schobi
Oct 14 '08 #22

This discussion thread is closed

Replies have been disabled for this discussion.