2012-11-11 22 views
10

私はCodeProjectでいくつかのコードを使い、C++のキャストのために次のコードを見つけました。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」アプローチより優れています。 –

+0

おそらくそれは恐ろしいキャストという名前です。基本的には、コンパイラ固有の動作を実装することです。 – KodeWarrior

答えて

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を使用しても2回ですが、実際は引数としてconst InputClass& inputを使用する方が効率的です)。元のオブジェクトに変更を加えることなく、結果を直接操作することができます。

これは正確には何が... hmに役立つのですか?私は本当に良いユースケースはないと思っています。チェックされていないキャストは常に避けるべきです.David Hammenは、これは実際には完全に定義されていないと述べています。

+0

彼らの店には 'reinterpret_cast'に対するポリシーがありますが、この抜け穴はありません。 – Barmar

+0

それを使うのはさらに恐ろしいでしょう: 'reinterpret_cast'は危険ですが、これは悪いです。 – leftaroundabout

+0

個人的に、私はこのようなキャストを隠すよりも、 'reinterpret_cast'(そしてそれに対してルールがあれば放棄しなければならないかもしれない)を見るほうがはるかに好きです。 –