Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementation of C++ Cast

I was going through some code in CodeProject and came across the following code for C++ casting.

template <class OutputClass, class InputClass>
union horrible_union{
    OutputClass out;
    InputClass in;
};
template <class OutputClass, class InputClass>
inline OutputClass horrible_cast(const InputClass input){
    horrible_union<OutputClass, InputClass> u;
    u.in = input;
    return u.out;
}

Why is the cast implemented the above way. Why can't we just do a manual cast. Can someone give an example of when a normal cast wouldn't work ?

like image 799
KodeWarrior Avatar asked Nov 11 '12 19:11

KodeWarrior


People also ask

How does C cast work?

Type Casting is basically a process in C in which we change a variable belonging to one data type to another one. In type casting, the compiler automatically changes one data type to another one depending on what we want the program to do.

What is C style cast?

C-style casts can be used to convert any type into any other type, potentially with unsafe results (such as casting an integer into a pointer type). (<type>)<value> This example casts an int to a double for the purpose of avoiding truncation due to integer division: double result = (double)4/5; Popular pages.

What happens when casting in C?

Type casting refers to changing an variable of one data type into another. The compiler will automatically change one type of data into another if it makes sense. For instance, if you assign an integer value to a floating-point variable, the compiler will convert the int to a float.

Which type casting is accepted by C?

6. Which of the following typecasting is accepted by C? Explanation: None.


2 Answers

This approach basically lets you get away with any cast, although it relies on undefined behavior.

A normal cast would complain when casting between unrelated types, whereas this wouldn't.

struct A{};
struct B{};

template <class OutputClass, class InputClass>
union horrible_union{
    OutputClass out;
    InputClass in;
};
template <class OutputClass, class InputClass>
inline OutputClass horrible_cast(const InputClass input){
    horrible_union<OutputClass, InputClass> u;
    u.in = input;
    return u.out;
}

int main()
{
    A a;
    B b;
    a = horrible_cast<A,B>(b);   //this compiles
    a = reinterpret_cast<A>(b);  //this doesn't
} 

Bottom line: it's horrible, don't do it.

like image 89
Luchian Grigore Avatar answered Oct 03 '22 06:10

Luchian Grigore


Using a union in this way is in general roughly equivalent to a hard reinterpret_cast of pointers. However, that doesn't copy objects, your example does (twice even with RVO, in fact; it would be rather more efficient to have const InputClass& input as the argument). So you can directly operate on its result without possibly mutating the original object.

What exactly this is useful for... hm. I don't think there's any really good use case, unchecked casts should always be avoided, and as David Hammen remarked this one is actually completely undefined (though it will normally work, if used "correctly").

like image 28
leftaroundabout Avatar answered Oct 03 '22 06:10

leftaroundabout