0

In the following case I try to cast a pointer to a struct into a pointer to another struct (which has the same memory layout behind the scenes). I try to do this in a const correct way, however the compiler is complaining.

I looked at a similar issue but I need the constness to propagate and it doesn't work like described for me.

Demo

struct queue
{
    // ...
};

typedef struct queue* queue_handle;

struct dummy_queue
{
    // ...
};

struct queue_wrapper
{
    auto get_queue() const -> queue_handle {
        return reinterpret_cast<const queue_handle>(&d);
    }

    dummy_queue d;
};

int main()
{
    queue_wrapper w;
    w.get_queue();
}

Error:

<source>: In member function 'queue* queue_wrapper::get_queue() const':
<source>:17:16: error: 'reinterpret_cast' from type 'const dummy_queue*' to type 'queue_handle' {aka 'queue*'} casts away qualifiers
   17 |         return reinterpret_cast<const queue_handle>(&d);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I'm converting to a const pointer though (which gcc seems to misunderstand somehow). I do not need to change the pointer after returning it. How do I accomplish this conversion without errors?

glades
  • 3,778
  • 1
  • 12
  • 34
  • 1
    `reinterpret_cast` is not for adding/removing cv-qualifiers. One possible solution is `typedef struct queue const* queue_handle;` – mada Oct 01 '22 at 14:57
  • `queue_handle` is a pointer to a non-const `queue`, but `d` is `const` in `get_queue()`. Are you sure you want to return a non-const pointer to a const member? Why is `get_queue()` declared as `const` in this example? – Remy Lebeau Oct 01 '22 at 16:56

1 Answers1

3

const queue_handle applies the const to the pointer type itself, not the pointed to type as you intent to.

I would suggest adding a const_queue_handle alias to const queue* if you are already using aliases for the pointers (whether or not that is a good idea is a matter of opinion) and then you can use that as template argument to reinterpret_cast.

Also beware that even if the struct layout is identical, this is still undefined behavior territory. A compiler may assume that a pointer to one of the struct types won't alias one to the other and use that for optimization. You should probably at least compile everything with -fno-strict-aliasing when doing this.

user17732522
  • 53,019
  • 2
  • 56
  • 105