読者です 読者をやめる 読者になる 読者になる

D3DX のベクトル型の罠

DirectX

久しぶりにコードの出てくる Direct3D 話.
次のコードはコンパイル可能か?

#include <d3dx9.h>
#include <iostream>

int main()
{
    D3DXVECTOR2 vec2(0.0f, 1.0f);
    D3DXVECTOR3 vec3 = vec2;
    std::cout << vec3.z;

    return 0;
}









答え.可能.
まず D3DXVECTOR2 を見てみる.

//--------------------------
// 2D Vector
//--------------------------
typedef struct D3DXVECTOR2
{
#ifdef __cplusplus
public:
    D3DXVECTOR2() {};
    D3DXVECTOR2( CONST FLOAT * );
    D3DXVECTOR2( CONST D3DXFLOAT16 * );
    D3DXVECTOR2( FLOAT x, FLOAT y );

    // casting
    operator FLOAT* ();
    operator CONST FLOAT* () const;
    (以下略)

次に D3DXVECTOR3 を見てみる.

//--------------------------
// 3D Vector
//--------------------------
#ifdef __cplusplus
typedef struct D3DXVECTOR3 : public D3DVECTOR
{
public:
    D3DXVECTOR3() {};
    D3DXVECTOR3( CONST FLOAT * );
    D3DXVECTOR3( CONST D3DVECTOR& );
    D3DXVECTOR3( CONST D3DXFLOAT16 * );
    D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z );

    // casting
    operator FLOAT* ();
    operator CONST FLOAT* () const;
    (以下略)

つまり,

    D3DXVECTOR3 vec3 = vec2;

    D3DXVECTOR3 vec3(static_cast<float*>(vec2));

と解釈される.
そして,D3DXVECTOR3 のコンストラクタは,大方の予想通り,読むべきではないところまで float だと思って読み進める.
嫌すぎる.
嫌すぎるので,私は D3DX で始まる構造体の CONST FLOAT* のみを受け取るコンストラクタ explicit を付け加えている.個人の環境でのみだけど.
そしてもしかなうことなら,DirectX SDK の今後のリリースでこれらのコンストラクタが明示的コンストラクタに修正されることを希望する.その困難さは承知の上で.
あちこちのプロジェクトでビルドが通らなくなりそうだけど,そのコンパイルエラーの何割かは,きっと本当にエラーが相応しい.

明示的なコンストラクタ

1変数を受け取るコンストラクタにはexplicitキーワードを使用してください。