views:

315

answers:

2

What is the difference between

(type)value

and

type(value)

in C++?

+14  A: 

There is no difference.

Edit: Since somebody downvoted this, I'll quote the standard (§5.2.3).

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).

Since the question specified the difference between type(value) and (type)value, there is absolutely no difference.

If and only if you're dealing with a comma-separated list of values can there be a difference. In this case:

If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5, 12.1), and the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as an rvalue.

Edit: As Troubadour pointed out, there are a certain types for which the type(value) version simply won't compile. For example:

char *a = (char *)string;

will compile, but:

char *a = char *(string);

will not.

Jerry Coffin
Only for built-in types.
Troubadour
Um, no there is no difference. +1
Johannes Schaub - litb
Well, maybe :) But what about untypedef'ed pointer types?
Troubadour
+1, surprising.
JaredPar
For the record, I didn't downwovte.
Troubadour
And *if* there is a comma separated list of expression, the first form cannot be used at all. It only works for single expressions of course. So in fact, in any circumstances, having a type named by `type`, then `type(value)` and `(type)value` is the same.
Johannes Schaub - litb
@litb: good point -- to try to include more than one expression, you'd have to do `(type)(expression-list)`, and at that point you'd just have redundant parens about the type...
Jerry Coffin
So nobody wants to answer my question about type being something like char*. The fact that it's a syntax error in the second case is okay is it? Oh, I guess that char* doesn't come under all types. You learn something new every day here. ;)
Troubadour
@Jerry, It's worse because you would cast the result of the comma operator.
Johannes Schaub - litb
@Troubadour, the question was about `type`, not about `type*`. It still works for all types, because making a suitable typedef will make `type` denote `char*`.
Johannes Schaub - litb
@litb: What a load of nonsense. char* is a perfectly good type. It could be used as T in template<class T>. I know you can use typedef to circumvent it, but then you would have known that if you'd read my earlier comment.
Troubadour
Well, I took it as a question about the difference in meaning between the two (when they compile). You're certainly right, however, that some "types" must be parenthesized for the code to compile at all. My apologies for the previous comment -- I missed your point entirely.
Jerry Coffin
@Troubadour, i see now what you mean. But what i said was that it works for all types, not just for "builtins" like you said. The point is that `char*` and `identity<char*>::type` (for a template like `boost::mpl::identity`) and `type` when `type` was typedefed to `char*` all denote the same type. The question is worded in such a way that `type` should denote a type (obviously). `type` grammatically is a simple-type-specifier, but `char*` is not. It's a `type-id`, which you can pass as template arguments. Also, please don't insult people by saying they write "nonsense".
Johannes Schaub - litb
So, it's wrong to say that "there are a certain types for which the type(value) version simply won't compile [but for which the other version will]", because it certainly compiles for the type denoted by `char*` - if you typedef it or if you write it as `identity<char*>::type(value)`
Johannes Schaub - litb
@litb: Yes, I've already accepted I was wrong about built-ins. Right away in fact. The question is about as short as it gets and is worded in no such way that you can draw any conclusions about type.
Troubadour
@litb: Oh, and please don't insult people by responding to comments that you've only half-read.
Troubadour
To show a better example: I tell you that `a * b` is equal to `b * a` and you say "No, that's not true for a = 1 and b = 2, because: `0+1 * 2` is 2 and `2 * 0+1` is 1."
Johannes Schaub - litb
@litb: That's just childish.
Troubadour
+3  A: 

There is no difference; the C++ standard (1998 and 2003 editions) is clear about this point. Try the following program, make sure you use a compiler that's compliant, such as the free preview at http://comeaucomputing.com/tryitout/.

#include <cstdlib>
#include <string>
int main() {
  int('A'); (int) 'A'; // obvious
  (std::string) "abc"; // not so obvious
  unsigned(a_var) = 3; // see note below
  (long const&) a_var; // const or refs, which T(v) can't do
  return EXIT_SUCCESS;
}

Note: unsigned(a_var) is different, but does show one way those exact tokens can mean something else. It is declaring a variable named a_var of type unsigned, and isn't a cast at all. (If you're familiar with pointers to functions or arrays, consider how you have to use a parens around p in a type like void (*pf)() or int (*pa)[42].)

(Warnings are produced since these statements don't use the value and in a real program that'd almost certainly be an error, but everything still works. I just didn't have the heart to change it after making everything line up.)

Roger Pate
Nice code formatting, was that intended?
squelart
@squelart: Not at first, but once it got close I worked it in, and just didn't have the heart to change it in order to get rid of the warnings.
Roger Pate