473,386 Members | 1,842 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Casts that look like function calls?

I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)

I asked him what that was, and he said "it's a cast." I know all about
dynamic_cast and friends, but this was something new to me. To make a
long story short, both of my colleagues seemed to be familiar with
writing a cast as if it were a function, although they don't normally
write them that way, and Stoustrup's book has actual instances of this
that appear in some of his code examples. A colleague was able to find
something in the formal C++ syntax description indicating it's valid...
but nobody was able to point me to any documentation, description, or
explanation.

If this is described in Stroustrup's book, I couldn't find it. I
thought "deprecated C-style cast" might be it, but, no, that's just the
regular C cast syntax, and I've verified that C compilers do _not_
accept writing a cast as if it were a function.

It is not a Microsoft-ism, either, which was my other thought; other
C++ compilers seem to accept it.

So, what the heck is it? Is it fully legitimate C++? Does it have any
differences whatsoever from a "normal" cast, i.e. do

hij = long(klm);
and
hij = (long) klm;

compile identical code? If so, what is it there for? Is it just an
unintended consequence of things that needed to be done to extend C
syntax to C++? And where exactly in Stoustrup's book is it described
and explained?

Jan 18 '07 #1
13 1558
dp*********************@gmail.com schrieb:
I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)
This is normal constructor syntax. Assuming that BOOL is a type and not
a function name the above line constructs a variable of type BOOL from
def, which is not the same as a cast from def to BOOL. If BOOL is a
class or struct the code will only compile if BOOL has a constructor
that takes an argument of def's type. If BOOL is a typedef for a
primitive type the code will compile if def is convertable to that
type. Only in the latter case is the above line comparable to a cast.

Ralpe

Jan 18 '07 #2

ralpe ha escrito:
dp*********************@gmail.com schrieb:
I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)
To me, it is defined as a macro that does the simple cast and should be
defined as:

#define BOOL(x) (bool) x

as you can see, everytime the BOOL(x) macro is called, the preprocessor
will transform it onto (bool) x.

I do not see the macro usage useful and it makes the code very hard to
read and understand. The

Jan 18 '07 #3
ralpe <ra************@gmx.netwrote:
dp*********************@gmail.com schrieb:
>I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)

This is normal constructor syntax. Assuming that BOOL is a type and not
a function name the above line constructs a variable of type BOOL from
def, which is not the same as a cast from def to BOOL. If BOOL is a
class or struct the code will only compile if BOOL has a constructor
that takes an argument of def's type. If BOOL is a typedef for a
primitive type the code will compile if def is convertable to that
type. Only in the latter case is the above line comparable to a cast.
Also, the function-style cast will not work for types that have a space
in them (e.g., "unsigned long").

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 18 '07 #4
On Jan 18, 3:08 pm, dpbsmith.janissary.2...@gmail.com wrote:
I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)
I would suspect that this is actually a macro since there is no
BOOL-type in C++. BOOL is probably a macro looking something like this:

#define BOOL(x) x 0 ? 1 : 0;
I asked him what that was, and he said "it's a cast." I know all about
dynamic_cast and friends, but this was something new to me. To make a
long story short, both of my colleagues seemed to be familiar with
writing a cast as if it were a function, although they don't normally
write them that way, and Stoustrup's book has actual instances of this
that appear in some of his code examples. A colleague was able to find
something in the formal C++ syntax description indicating it's valid...
but nobody was able to point me to any documentation, description, or
explanation.

If this is described in Stroustrup's book, I couldn't find it. I
thought "deprecated C-style cast" might be it, but, no, that's just the
regular C cast syntax, and I've verified that C compilers do _not_
accept writing a cast as if it were a function.

It is not a Microsoft-ism, either, which was my other thought; other
C++ compilers seem to accept it.

So, what the heck is it? Is it fully legitimate C++? Does it have any
differences whatsoever from a "normal" cast, i.e. do

hij = long(klm);
and
hij = (long) klm;
My compiler takes both of them without any problem. A guess would be
that there somewhere in the standard says that there should exist
functions with the same name as the basic types that returns a value of
that type (so you can use it kind of like a constructor) which might be
what the second is.

--
Erik Wikström

Jan 18 '07 #5
dp*********************@gmail.com wrote:
[function-style casts]
And where exactly in Stoustrup's book is it described
and explained?
I found it in Section 6.2.8 - Constructors (p.131 in the Special
Edition).

The T(e) construct is sometimes referred to as a function-style cast.
Unfortunately, for a built-in type T, T(e) is equivalent to (T)e
(section 6.2.7).

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 18 '07 #6

ralpe wrote:
dp*********************@gmail.com schrieb:
I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)

This is normal constructor syntax. Assuming that BOOL is a type and not
a function name the above line constructs a variable of type BOOL from
def, which is not the same as a cast from def to BOOL.
Not true. It is, in fact, a cast. It has exactly the same meaning as
(BOOL)def. Many people, myself included for a long time, assume that
such "constructor calls" are just that. For instance:

std::string x = std::string("Hello ") + "World!";

The call "std::string("Hello")" is a _cast_, not a constructor call or
initialization. It resolves to the same thing as:

std::string x = (std::string)"Hello " + "World";

or

std::string x = static_cast<std::string>("Hello ") + "World";

Now all these casts eventually resolve to a constructor invocation
because in order to cast to that type an instance of that type must be
constructed. However, these are in fact casts and as a form of C-Style
cast they have the same weakness (can resolve to a reinterpret without
warning).

Do a search in this group for discussions about "constructor calls" and
whether or not such a thing even exists. Many argue that there is no
way for the programmer to directly "call" the constructor. The
standard calls all things that look like constructor calls either
"function style cast" or "initialization".

Even though our in our coding standard we don't allow C-style casts (I
finally convinced everyone this was necissary) we do allow such
function style casts in cases such as "string construction".

<quote>
Function style casts have the same problems as c-style casts and can be
used in place of them. They are allowed in one case only; that is when
they look like a constructor call:

extern const char * str; std::string s = std::string("Hello") +
str;

It is often assumed that the case "std::string("Hello")" is a
constructor call but it is actually a cast. When you could normally
construct an object with a parameter of that type (using "new
TYPE(x)"), a function style cast is allowed. Under no other condition
will you use one.
</quote>

Jan 18 '07 #7

Marcus Kwok wrote:
dp*********************@gmail.com wrote:
[function-style casts]
And where exactly in Stoustrup's book is it described
and explained?

I found it in Section 6.2.8 - Constructors (p.131 in the Special
Edition).

The T(e) construct is sometimes referred to as a function-style cast.
Unfortunately, for a built-in type T, T(e) is equivalent to (T)e
(section 6.2.7).
Stroustrup seems to deviate from the standard here then. I have to
admit that I have never read his book.

5.2.3 Explicit type conversion (functional notation)

1 A simple type specifier (7.1.5) followed by a parenthesized
expression-list constructs a value of the specified type given the
expression list. If the expression list is a single expression, the
type conversion expression is equivalent (in definedness, and if
defined in meaning) to the corresponding cast expression (5.4).

Sumarizing the rest: if it is a class type it must be complete. I the
parameter list is more than one expression it is equivelent to creating
and initializing a temporary rvalue of type T.

Jan 18 '07 #8
Noah Roberts <ro**********@gmail.comwrote:
Marcus Kwok wrote:
>dp*********************@gmail.com wrote:
[function-style casts]
And where exactly in Stoustrup's book is it described
and explained?

I found it in Section 6.2.8 - Constructors (p.131 in the Special
Edition).
[quote moved below]
>
Stroustrup seems to deviate from the standard here then. I have to
admit that I have never read his book.
Hmm, maybe this can be reconciled by the part that I didn't quote.
5.2.3 Explicit type conversion (functional notation)

1 A simple type specifier (7.1.5) followed by a parenthesized
expression-list constructs a value of the specified type given the
expression list.
Before the other passage I quoted, he also states:

The construction of a value of type T from a value e can be expressed
by the functional notation T(e).

and then gives an example of usage.

[quote from the Standard]
If the expression list is a single expression, the
type conversion expression is equivalent (in definedness, and if
defined in meaning) to the corresponding cast expression (5.4).
[original quote from Stroustrup]
> The T(e) construct is sometimes referred to as a function-style cast.
Unfortunately, for a built-in type T, T(e) is equivalent to (T)e
(section 6.2.7).
With that addition, I don't see how it deviates from the passage from
the Standard, though I have to admit that I haven't read the entire
Standard in depth, nor am I an expert in Standardese.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Jan 18 '07 #9
ralpe wrote:
dp*********************@gmail.com schrieb:
>I know C++ mostly from "learning by doing." My main reference is
Stoustrup's book. I was puzzled by something in a colleague's code that
looked like this:

abc=BOOL(def)

This is normal constructor syntax.
It isn't a constructor syntax at all. It's an explicit conversion
(function style) according to the specification. The word BOOL
here need not be the name of a constructor. It can be any type
name, even a typedef.
>Only in the latter case is the above line comparable to a cast.
Completely and totally incorrect. Any time a function-style
conversion is used with exactly one argument it is EXACTLY
equivelent BY DEFININTION to the cast style conversion.
Jan 18 '07 #10
Marcus Kwok wrote:
dp*********************@gmail.com wrote:
[function-style casts]
> And where exactly in Stoustrup's book is it described
and explained?

I found it in Section 6.2.8 - Constructors (p.131 in the Special
Edition).

The T(e) construct is sometimes referred to as a function-style cast.
Unfortunately, for a built-in type T, T(e) is equivalent to (T)e
(section 6.2.7).
For any type.
Jan 18 '07 #11
Summing up: here's what I think I've gleaned. (Oh, I forgot to explain:
BOOL is a Microsoft-ism, but it is not a macro that takes arguments,
it's just typedef int BOOL;)

Suppose we have an explicit class, rather than a built-in type, like

const int five = 5;
class foo {
public:
foo(int x);
}

1) Then foo(five) is _not_ a "call to a constructor function;" it is,
semantically, a _cast_ of an "int" to a "foo". However, performing the
cast involves invoking the constructor. Sounds like Humpty-Dumpty
language to me, but OK.

2) Therefore, in C++, the syntax C(e), where C is a programmer-defined
class, is a cast, not a function call.

3) It sounds to me like an _unintended side effect,_ that occurred in
order to avoid complicating the syntax, that T(e), where T is a
built-in type like "long" or "float," is also a cast.

4) It is _completely equivalent to_ (generates the same code as) C
casting syntax.

5) I can't quite make out what Stoustrup is saying when he says
"Pointer conversions cannot be expressed using the T(e) notation. For
example, char*(2) is a syntax error. Unfortunately, the protection that
the constructor notation provides against such dangerous conversions
can be circumvented by using typedef names." This sounds as if he first
makes a recommendation to use the T(e) notation on the basis of safety,
then noting that it doesn't actually provide safety.

6) If it is not an unintended side-effect, then it seems to be
motivated by some need for it in templates.

7) It does not seem as if there's any particular reason to prefer this
notation, or use it at all, except when writing templates. It would
seem to me that anyone doing C-style casts _of pointers_ would have to
be aware of what they are doing. It's not the case that habitually
using these constructor-style casts would give you protection against
mental lapses or anything like that?

Jan 19 '07 #12
dp******@gmail.com wrote:
1) Then foo(five) is _not_ a "call to a constructor function;" it is,
semantically, a _cast_ of an "int" to a "foo". However, performing the
cast involves invoking the constructor.
It's never a call to the constructor, even in the case of other than
exactly one argument. You can't call constructors directly,
constructors don't have return value, etc... It's a creation
of a temporary object which involves storage allocation, and
a few other things in addition to the invocation of the constructor.
>
2) Therefore, in C++, the syntax C(e), where C is a programmer-defined
class, is a cast, not a function call.
It's never a function call when C is a type name.
>
3) It sounds to me like an _unintended side effect,_ that occurred in
order to avoid complicating the syntax, that T(e), where T is a
built-in type like "long" or "float," is also a cast.
Huh? It's always a cast. It's never a function call.
>
4) It is _completely equivalent to_ (generates the same code as) C
casting syntax.
Yes.
>
Jan 19 '07 #13
* dp******@gmail.com:
Summing up: here's what I think I've gleaned. (Oh, I forgot to explain:
BOOL is a Microsoft-ism, but it is not a macro that takes arguments,
it's just typedef int BOOL;)

Suppose we have an explicit class, rather than a built-in type, like

const int five = 5;
class foo {
public:
foo(int x);
}

1) Then foo(five) is _not_ a "call to a constructor function;" it is,
semantically, a _cast_ of an "int" to a "foo". However, performing the
cast involves invoking the constructor. Sounds like Humpty-Dumpty
language to me, but OK.
It is /syntactically/ a cast.

A cast is a syntax concept, what you write. A conversion is a semantic
concept, what happens. For example

int x;
double y = 4.56;
x = y; // This is a conversion, but it's not a cast.

What happens for foo(five) depends on the type that foo is.

While we're on the topic of terminology, I see that Ron has jumped in
criticizing your use of "call constructor".

The standard and most everyone else use your terminology.

2) Therefore, in C++, the syntax C(e), where C is a programmer-defined
class, is a cast, not a function call.
Almost right. The "therefore" is meaningless.

3) It sounds to me like an _unintended side effect,_ that occurred in
order to avoid complicating the syntax, that T(e), where T is a
built-in type like "long" or "float," is also a cast.
It's not clear why it turned out this way. But it's all bound up with
the (1) the idea of converting constructors, and (2) the idea that
terseness, having things done implicitly for you, is extremely valuable.
At least one of those was perhaps not such a good idea.

4) It is _completely equivalent to_ (generates the same code as) C
casting syntax.
Yes.

5) I can't quite make out what Stoustrup is saying when he says
"Pointer conversions cannot be expressed using the T(e) notation. For
example, char*(2) is a syntax error. Unfortunately, the protection that
the constructor notation provides against such dangerous conversions
can be circumvented by using typedef names." This sounds as if he first
makes a recommendation to use the T(e) notation on the basis of safety,
then noting that it doesn't actually provide safety.
T(e) requires T to be a "simple type-specifier", which is a possibly
namespace- or class- qualified class, enum, typedef or built-in type name.

6) If it is not an unintended side-effect, then it seems to be
motivated by some need for it in templates.
No, the basic syntax is older than templates.

7) It does not seem as if there's any particular reason to prefer this
notation, or use it at all, except when writing templates. It would
seem to me that anyone doing C-style casts _of pointers_ would have to
be aware of what they are doing. It's not the case that habitually
using these constructor-style casts would give you protection against
mental lapses or anything like that?
The T(e) notation does not protect you against anything.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jan 19 '07 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Michael Wagner | last post by:
I do some Windows kernel programming, where what I need to pass to some Kernel call is "void* Context". Sometime later, I will get that Conext back. I want to pass a class pointer to this system...
3
by: Howard | last post by:
Hi, I am maintaining a lot of code that is rife with C-style casts. I've seen a lot of comments that one should not use C-style casts at all. But I'm wondering what harm there could be in...
31
by: Jacob | last post by:
It is a common recommendation to use "static_cast<SomeType> someInstance" instead of the traditional infamous "(SomeType) someInstance". Should I use the same practice for simple types, i.e....
47
by: sunglo | last post by:
Some time a go, in a discussion here in comp.lang.c, I learnt that it's better not to use a (sometype **) where a (void **) is expected (using a cast). Part of the discussion boiled down to the...
21
by: Andreas Huber | last post by:
Hi there Spending half an hour searching through the archive I haven't found a rationale for the following behavior. using System; // note the missing Flags attribute enum Color {
10
by: Ralf | last post by:
Regarding numerical types, in my view, casts fall in one of two categories: 1. Casts that change the value of an object 2. Casts that are actually redundant, but get rid of compiler/lint warnings...
9
by: liljencrantz | last post by:
Hi, I have a piece of code that uses hashtables to store pointers to various bits of data. The hashtable sees all pointers as const void *, while the application obviously uses various other...
2
by: Noah Roberts | last post by:
I have a class, that inherits from a class that inherits virtually from another class. I have a breakdown occuring and it is not wrt the virtually inherited class but one of the other MIed pure...
81
by: jacob navia | last post by:
Hi I am still writing my tutorial book about C. Here is the section about casts. I would be interested in your opinions about this. Some people have definite views about this subject ("never...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.