3

There are a couple of questions with similar names on StackOverflow, such as this one and this one .etc

However, none of them answered the questions in my mind...

Problem Background:

I'm including a C header file in C++ code. The problematic C code is shown below:

// C header file
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
    const pkg_req_t *pkg = packagevoid;
    ...
    ... // some other code
}

The compiler complained that:

/<project_path>/handler_util.h:250:26: error: invalid conversion from 'const void*' to 'const const pkg_req_t*' {aka 'const pkg_req_s*'} [-fpermissive]
const pkg_req_t *pkg = packagevoid;
                       ^~~~~~~

I changed the conversion to explictly use static_cast:

// C header file: fixed
static inline bool post_request(const customer_t *requester, const void *packagevoid)
{
#ifdef __cplusplus
  const pkg_req_t *pkg = static_cast<const pkg_req_t*>(packagevoid);
#else
   const pkg_req_t *pkg = packagevoid;
#endif
    ...
    ... // some other code
}

Questions:

  1. const pkg_req_t *pkg = packagevoid; --- why this is legal in C but giving error in C++?
  2. Is static_cast an elegant solution in this case? --- I'm asking this question because it appears that const_cast<pkg_req_t*>reinterpret_cast<const pkg_req_t*> also works. Which one is better?
  3. In the compilation error message, why is the compiler reporting "[-fpermissive]" in the end of the error message?
ZR_xdhp
  • 361
  • 2
  • 13

1 Answers1

4

why this is legal in C but giving error in C++?

In C++, implicit conversion from void* to T* is not allowed because it is not a "safe" conversion. Dereferencing the T* would cause undefined behaviour unless the void* actually did point to a T object.

By the time C++ was created, it was too late to ban this type of implicit conversion in C because it would break all the code that does this:

T* p = malloc(sizeof(T));  // malloc returns void*

Therefore, it continues to be allowed in C.

Is static_cast an elegant solution in this case?

Yes, that's the "best practices" way to perform a conversion from const void* to const T*.

static_cast is less dangerous than const_cast and reinterpret_cast, so it should be preferred over them. dynamic_cast is less dangerous than static_cast, but it cannot be used in this situation.

In the compilation error message, why is the compiler reporting "[-fpermissive]" in the end of the error message?

The compiler is telling you that if you compile your code with the -fpermissive flag, it will accept the implicit conversion from const void* to const T* even though the standard does not allow it.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • 1
    Using `reinterpret_cast` is also a way to warn/spot that that cast is not secure. whereas `static_cast` won't raise so much attention from reviewer IMO. – Jarod42 Feb 26 '20 at 18:25
  • Why `dynamic_cast` cannot be used in this situation? – ZR_xdhp Feb 27 '20 at 10:30
  • 1
    @ZuckerReis `dynamic_cast` only performs safe conversions. There is no way to safely check whether a `void*` points to the desired type. – Brian Bi Feb 27 '20 at 15:44
  • `dynamic_cast` only works on class types with at least one virtual function. – RL-S Nov 09 '22 at 12:24