Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ static_cast from float** to void**

Tags:

c++

Just ran into this:

#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    float *a = new float[10];
    void **b;
    b = static_cast<void**>(&a);
    delete(a); 
    return 0;
}

macbook:C nils$ g++ -Wall -g -o static_cast static_cast.cpp 
static_cast.cpp: In function ‘int main(int, char**)’:
static_cast.cpp:9: error: invalid static_cast from type ‘float**’ to type ‘void**’
macbook:C nils$ clang++ -Wall -g -o static_cast static_cast.cpp 
static_cast.cpp:9:9: error: static_cast from 'float **' to 'void **' is not
      allowed
    b = static_cast<void**>(&a);
        ^~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
macbook:C nils$ 

Why is it not allowed? While b = (void**)(&a); works.

like image 557
Nils Avatar asked Sep 02 '10 08:09

Nils


2 Answers

$5.2.9/2 -

"An expression e can be explicitly converted to a type T using a static_cast of the form static_cast(e) if the declaration “T t(e);” is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is a reference type (8.3.2), and an rvalue otherwise. The expression e is used as an lvalue if and only if the initialization uses it as an lvalue."

Let us take the case of Code snippet 1 as below

float *f;

void *p = f;

Here initialization of 'p' is well-formed. This is in accordance with $4.2

An rvalue of type “pointer to cv T,” where T is an object type, can be converted to an rvalue of type “pointer to cv void.”

Now let us take the code in OP

In our case, 'E' is 'float **' and 'T' is 'void **'

So, whether static_cast will work for the attempted conversion if 'p' can be initialized as shown below

float **f;

void **p = f;

The initialization of 'p' is ill-formed as it is not a valid condition listed under $4.10

Now, coming to why b = (void**)(&a); works?

This is the case where an explicit cast is used ($5.4). In this case, this explicit cast is equivalent of reinterpret_cast ($5.4/5). In this particular case, this conversion is allowed ($5.2.1/7).

Does this help?

like image 51
Chubsdad Avatar answered Oct 05 '22 22:10

Chubsdad


See Should I use static_cast or reinterpret_cast when casting a void* to whatever.

you should use reinterpret_cast.

I've used static cast to cast from a child class to the parent class, or where I knew the the type conversion was safe. If I needed runt time verification, then I'd use dynamic_cast.

like image 28
Preet Sangha Avatar answered Oct 05 '22 22:10

Preet Sangha