1

The following code gives a compiler error in C++:

const double** x;
const void** y = x;

How do you get a const-safe equivalent?

Of course, you can get this to work with a simple cast:

const void** y = (const void**) x;

But surely the compiler should know that this ok? Why does it complain?

Blaise
  • 185
  • 2
  • 8

2 Answers2

3

Why should the compiler know that that is OK? I think you want the following instead

void *y = x;
x = static_cast<const double**>(y); // casting back needs static_cast or c-style cast

A void** doesn't have the special properties that a void* has (that of being an universal data pointer).

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    +1 for the last note: I remember reading somewhere that `const void**` shouldn't be used as a generic pointer for `const T**` types, but unfortunately it's not a very google friendly search term. – Evan Teran Nov 08 '10 at 18:22
  • There's also http://stackoverflow.com/questions/560845/what-are-the-often-misunderstood-concepts-in-c/566416#566416 – Johannes Schaub - litb Nov 08 '10 at 18:26
  • Personally I still prefer reinterpret_cast<> in these situations as it is guaranteed to work (casting to void* and back) and sticks out a lot more than static_cast<> thus making it more obvious that something funky is happening here. When you cast to void* something funky (And very high on the M.Fowler code smell meter) is going on. – Martin York Nov 08 '10 at 18:43
  • @Martin: I feel that `void*` in C++ already makes it clear enough that something funky is present. No need to use the cast that's easier to use dangerously. – Steve M Nov 08 '10 at 18:49
  • @Steve M: Lots of opaque objects use void* as the object that is passed around so void* in not that uncommon. In the visible code converting to/from void* is very uncommon though (as it is hidden inside a library that uses the opaque object) and should be highlighted (especially if you are writing that library). And reinterpret_cast<> is not dangerous for this as it is specifically designed for this situation. – Martin York Nov 08 '10 at 19:17
  • `reinterpret_cast` cannot cast to or from `void*` from or to another pointer type in that way. Of the C++ style casts, only `static_cast` can do that (compilers allow to also use `reinterpret_cast`, but only because disallowing it would break too much code). That's why in the comment I haven't included `reinterpret_cast`. – Johannes Schaub - litb Nov 08 '10 at 19:25
  • @Martin: `void*` is a bad choice for an opaque object type. A forward-declared class is more typesafe and doesn't require any casting in the library's implementation. But I digress. Sorry for expressing myself badly before - I don't mean that reinterpret_casting from `void*` is dangerous, but that reinterpret_cast is dangerous in general. It should appear less frequently than `void*` and be limited to interfacing with low-level APIs that actually reinterpret data, like Berkeley sockets. If reinterpret_cast were designed specifically for `void*` casts, static_cast wouldn't be so designed. – Steve M Nov 08 '10 at 19:38
  • @litb: You definitely can use reinterpret_cast to convert from T* -> void* -> T* and are guaranteed the result is the original value. @Steve M: Totally agree. (void* is a bad idea for opaque pointers (but it is common), Yes it should definitely be limited to interfacing with low level APIs. (But is that not exactly what the above code is doing)). static_cast() (in my mind) is for converting between similar types (so basically anything that does not involve `void*` where the compiler can do some actual work. – Martin York Nov 08 '10 at 20:21
  • @litb: @Steve M: The whole point of static_cast() is so that the compiler can do some compile time checking and thus reassure the user that some automated validation had been done. By using `void*` no such checking can be performed and this to me provides a false sense of security (which to me is bad). Reinterpret_cast() gives no guarantees() and thus requires more scrutiny; casting to/from void* provides no guarantees and thus requires more scrutiny. Why have two different things that you need to scrutinize in your code and simplify it to a single thing that needs close scrutiny. – Martin York Nov 08 '10 at 20:25
  • @Steve M: In general any casting is dangerous (because you are telling the compiler that you know better than it does). I would no more trust a reinterpret_cast than I would a const_cast – Martin York Nov 08 '10 at 20:29
  • @Martin nope. It's not allowed in C++03. Only C++0x is going to allow it. See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1120 and http://stackoverflow.com/questions/310451/should-i-use-static-cast-or-reinterpret-cast-when-casting-a-void-to-whatever/311178#311178 – Johannes Schaub - litb Nov 08 '10 at 20:38
  • Thanks for all this! If I understand correctly it's generally considered better to use void* for pointers to pointers than void** because of the special status of void*. Following on from @Evan's points - is there something better as a generic pointer to const T** types? – Blaise Nov 09 '10 at 18:05
0

Why does it complain?

Because it's NOT OK.

There's a FAQ explaining why but I can't seem to find it right now.

Your C-Style cast resolves to a reinterpret_cast, which tells the compiler to ignore types.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125