Я просматривал некоторый код в CodeProject и наткнулся на следующий код для приведения в C ++.
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;
}
Почему актерский состав реализован вышеуказанным способом. Почему мы не можем просто сделать ручной бросок. Может ли кто-нибудь привести пример, когда обычное приведение не сработало?
Этот подход в основном позволяет вам избегать любого приведения, хотя он основан на неопределенном поведении.
Нормальное приведение будет жаловаться при приведении между несвязанными типами, тогда как это не будет.
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
}
Итог: это ужасно, не делай этого.
Использование объединения таким способом в целом примерно эквивалентно reinterpret_cast
указателей. Однако, это не копирует объекты, ваш пример делает (дважды даже с RVO, фактически; было бы гораздо более эффективно иметь const InputClass& input
в качестве аргумента). Таким образом, вы можете напрямую воздействовать на его результат, не изменяя первоначальный объект.
Чем именно это полезно для … хм. Я не думаю, что есть действительно хороший вариант использования, всегда следует избегать неконтролируемых приведений, и, как заметил Дэвид Хаммен, это на самом деле полностью не определено (хотя, как правило, оно будет работать, если используется «правильно»).