C++类型转换的实现

11

我正在 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;
}
为什么要以上述方式实现转换,为什么不能手动进行转换。能否举个例子说明普通转换不起作用的情况?

为什么采用这种方式进行类型转换,不能手动进行强制转换吗?能否举一个例子说明常规强制转换无法正常工作的情况?


4
在设置了不同的成员之后访问联合体的成员是未定义行为,所以任何方法都比这种可怕的 horrible_union 方法更好。 - David Hammen
可能这就是为什么它被称为可怕的转换。这基本上是为了实现一些编译器特定的行为。 - KodeWarrior
2个回答

9

这种方法基本上让您可以使用任何类型转换,尽管它依赖于未定义的行为。

普通转换在不同类型之间进行转换时会发出警告,但是这种方法不会。

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
} 

底线:这是可怕的,不要做。

1
如果您正在使用特定编译器(用于某些嵌入式系统)并且在特定架构上工作,那么进行仅适用于该架构的类型转换可能是一种有效的方法。但我同意这仍然是危险的。 - bitmask

2
使用联合方式通常等同于硬指针reinterpret_cast。但是,这不会复制对象,而您的示例却复制了两次(即使使用了RVO)。实际上,将const InputClass& input作为参数会更有效率。因此,您可以直接操作其结果,而不可能改变原始对象。
那么这究竟有什么用处呢...嗯。我认为没有真正好的用例,应始终避免未经检查的强制转换,正如David Hammen所指出的,这个完全未定义(尽管如果“正确”使用,它通常会工作)。

也许他们的商店有反对使用reinterpret_cast的政策,但是这个漏洞不在此列。 - Barmar
在这种情况下使用它甚至更可怕:reinterpret_cast是危险的,但这个更糟。 - leftaroundabout
就我个人而言,我更喜欢看到reinterpret_cast(如果有规定禁止使用,则需要申请豁免),而不是像这样隐藏转换。 - David Hammen
@bitmask:确实,联合体可以用于快速序列化,但不应以这种复制密集的模板函数的形式出现。 - leftaroundabout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接