Cast and parenthesis

Hello,

Here is a little piece of code:
1
2
int i = 5;
double l = double(int(i)) / double(int(i));

This code does compile (with gcc 4.6.3).

Let's add parenthesis:
double l = (double(int(i))) / double(int(i));
The code does compile again.

Let's change the / to a *:
double l = (double(int(i))) * double(int(i));
The code does not compile anymore:
error: invalid type argument of unary '*' (have 'double')

Now let's change the * to a +:
double l = (double(int(i))) + double(int(i));
Another compilation error is issued:
error: invalid cast to function type 'double(int)'

Removing the parenthesis:
double l = double(int(i)) + double(int(i));
and the code does compile again (and it does compile with a * as well).

I don't understand the difference between double(int(i)) without parenthesis and (double(int(i))) with parenthesis.
Can someone explain me ?

Thanks.
There are more kinds of cast styles in C++:
http://www.cplusplus.com/doc/tutorial/typecasting/

The traditional style cast, inherited from C:
(double)i;

The "functional" style cast, which mimics object constructors:
double(i);

And the new style casts, which use a keyword and are more specialized:
static_cast<double> (i); // there are others beside static_cast, read the link above

Basically what happens in your code is that you use the functional style cast, until you put parentheses around it making it a C style cast.

And then double(int) is the signature of a function returning a double and having an int parameter. You can't directly use double(int) as a type however (hopefully someone more knowledgeable than I can explain why not).

Below is an example demonstrating function pointers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

double f(int i)
{
    return i*i;
}

int main()
{
    typedef double(my_function)(int);

    my_function *pf = &f; // pointer to function

    std::cout << (*pf)(2) << std::endl;
}
4


Edit: and here's the C++11 version of the above example, which doesn't use typedef:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

double f(int i)
{
    return i*i;
}

int main()
{
    using my_function = double(int);

    my_function *pf = &f; // pointer to function

    std::cout << (*pf)(2) << std::endl;
}
4


You will need a modern compiler that supports the C++11 standard to compile the above. I'm using MinGW GCC 4.8.1, and Visual Studio 2012 should work as well.
Last edited on
Thanks Catfish4, now I understand the difference between double(int(i)) and (double(int(i))).

However, I don't understand why this code compiles:
1
2
3
4
5
6
7
8
#include <iostream>

int main() {
  int i = 5;
  double l = (double(int(i))) / double(int(i));
  std::cout << "l = " << l << std::endl;
  return 0;
}

I would have expected to get an error as the lhs of the / is a cast to function type, and the rhs is a double (am I correct ?). At least, the compiler could issue a warning telling that the lhs is ambiguous.
Last edited on
I would have expected to get an error as the lhs of the / is a cast to function type, and the rhs is a double (am I correct ?). At least, the compiler could issue a warning telling that the lhs is ambiguous.

MinGW GCC 4.8.1 gives no error or warning for the above code and I think it is because of this:

GCC will "figure out" that (double(int(i))) is a double "functional" style cast put in additional parentheses, because what follows is / denoting a division operation.

However when you use *, it considers the (double(int(i))) to be a C style cast because the operator * is considered to be the dereference operator, not the multiplication operator.

1
2
3
4
int i = 5 * 5; // multiplication operator (binary because it has two operands)

*p = 5; // dereference operator (unary because it has one operand)
// assume p is a pointer that is safe to use 

Last edited on
Topic archived. No new replies allowed.