2

Basically I am wondering whether something like

f(const void* a){
  // This is also what `(char**) a` would do behind the scenes
  char** string_a_ptr {reinterpret_cast<char**>(const_cast<void*>(a))}; 

  // ...

is possible while preserving the const qualifier.

My question came up during an exercise about C-Arrays in C++. Because of C, I had to pass a function pointer with const void* arguments. In this case it was pointing on an array of C-strings. To cast it to the correct type I had to cast the const away. Is there a way in C++ to get something like a "(const char*)*"` pointer?

I have tried out const char** (without the const_cast) which yields

reinterpret_cast from type ‘const void*’ to type ‘const char**’ casts away qualifiers

and (const*)*, which gives a syntax error

expected type-specifier before ‘(’ token

This is a purely academic question. I am aware, that the problem can be solved easier and saver using std::string and #include <algorithm>.

While I am at it, are there advantages of sometimes using C-constructions in C++ or should they always be avoided if possible? I only did some small scale exercise problems with C code in C++, but it already causes quite a few headaches and forces me to look really closely under the hood, even though I have written a fair amount of C code in my life. Or is it would you rather recommend using the extern C qualifier and writing C code in pure C?

maow
  • 2,712
  • 1
  • 11
  • 25
  • 1
    `const void*` would be `char* const*`. (It’s more obvious if you position the `const` qualifier consistently: `void const*`.) – Ry- Feb 02 '17 at 07:21
  • I understand. Rewriting this as `void const*` is exactly what solves my confusion. Thanks! – maow Feb 02 '17 at 07:33
  • 1
    "are there advantages of sometimes using C-constructions in C++" Yes. But you should always try to avoid them and know how much the C construct is costing you in readability, type-correctness or maintainability. In case of a `void*`that's all three of them you lose on. – dascandy Feb 02 '17 at 09:28

2 Answers2

4

That would be a char* const *.

There are three places in a double pointer to put const:

const char**

Pointer, to a pointer, to a character you cannot change.

char *const *

pointer, to a pointer you cannot change, to a character.

char ** const

pointer you cannot change, to a pointer, to a character.

You can mix these to make different parts const.

dascandy
  • 7,184
  • 1
  • 29
  • 50
2

I believe this is what you're looking for:

const char * const * string_a_ptr = static_cast<const char * const *>(a);

[Live example]

You could even drop the first const if you want (and it makes sense).

Explanation:

const void * a means that a points to something (void) which is const. Therefore, if you cast a to another pointer, it must also point to something that is const. In your case, you're casting it to a pointer to char*. That char* must therefore be const. The syntax for creating a constant pointer (not a pointer to a constant) is to put the const to the right of the *. Hence, char* const *.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455