0
#include <iostream>

class c1{
};

class c2{
};

int main(){
 c1 a;
 c2 b;
 //b = static_cast<c2>(a);   <-- will not compile
 
b = *reinterpret_cast<c2*>(&a);
  
 return 0;
}

b = static_cast<c2>(a); will not compile with this error:

no matching conversion for static_cast from 'c1' to 'c2'

Is using reinterpret_cast and doing a bit cast the only way of accomplishing this?

Dan
  • 2,694
  • 1
  • 6
  • 19
  • Haven't tried `bit_cast`, as it is C++20, but they should be the only way to go. Might be relevant: [C++20 bit_cast vs reinterpret_cast](https://stackoverflow.com/questions/53401654/c20-bit-cast-vs-reinterpret-cast) – Ranoiaetep May 08 '21 at 22:46
  • Why don't you use a `union`? – Neil May 08 '21 at 22:47
  • @Ranoiaetep I mean my manual bit cast i'm doing with `reinterpret_cast` above, this is also a type of bit casting. – Dan May 08 '21 at 22:47
  • You might want to consider - _"...Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:..."_ https://en.cppreference.com/w/cpp/language/reinterpret_cast – Richard Critten May 08 '21 at 22:49
  • 5
    Your code has undefined behaviour. A proper way is to write a user-defined conversion operator or an assignment operator. – rustyx May 08 '21 at 22:52
  • If both types are trivially copyable and have the same size, you can `memcpy` from `b` to `a`. – François Andrieux May 09 '21 at 02:45

1 Answers1

5

The proper way is to provide a way to convert one into the other. There are different ways to do this, this is one way:

struct c2;
struct c1{
    explicit operator c2 ();
};

struct c2{ };

c1::operator c2() { return {};}

int main(){
 c1 a;
 c2 b;
 b = static_cast<c2>(a);
  
 return 0;
}

However, if you insist on "unrelated"...

What is the proper way of casting objects to unrelated objects in C++

There is none.

reinterpret_cast is a nice way to make the compiler silent, but b = *reinterpret_cast<c2*>(&a); is undefined behavior. Often reinterpret_cast is expected to be a magic any-to-any cast, which it isn't. See here for the rather limited list of cases that are defined. Casting between objects of unrelated types is not on the list.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • I'll have to read about `std::bit_cast` though if "unrelated" includes no relation between `sizeof(c1)` and `sizeof(c2)` then this answer needs no update afaik also for C++20. In any case "proper" way is to do a "proper" conversion ;) – 463035818_is_not_an_ai May 08 '21 at 23:14
  • Why would this be undefined if their size is the same? it's literally saying `interpret this chunk of memory as this type`, seems pretty defined. It's like regular bit cats in C. – Dan May 09 '21 at 00:28
  • I have also used `-fsanitize=undefined` on g++ and it doesn't produce an error during runtime, I don't think this is UB a slog as the object sizes are the same. – Dan May 09 '21 at 01:07
  • lastly, point 11 in your link says `A pointer to member object of some class T1 can be converted to a pointer to another member object of another class T2`. which seems to be what I'm doing here? – Dan May 09 '21 at 01:08
  • 3
    @Dan Yes, you are simply converting *a pointer* of type `c1*` into *a pointer* of type `c2*`. That much is well-defined. What is not defined is *accessing* a `c1` object *as-if* it were an unrelated `c2` object, which is what happens when you dereference the casted pointer and assign the result to `b`. See [what is type punning & what is the purpose of it?what happens if i use it or not use it?](https://stackoverflow.com/questions/44137442/) and [What is the strict aliasing rule](https://stackoverflow.com/questions/98650/) – Remy Lebeau May 09 '21 at 01:42
  • @RemyLebeau thanks i'm going to make another post about this topic. – Dan May 09 '21 at 02:36
  • here it is: https://stackoverflow.com/questions/67453977/use-the-same-memory-with-variables-of-2-different-types-without-causing-undefine – Dan May 09 '21 at 03:11