C++ と WinAPI の組み合わせって

相性悪いよなぁ…と強く思う今日この頃。^^;

例えば、文字列を扱うのに std::basic_string<TCHAR> を利用したとします。で、Win32API で「文字列へのポインタ」と「文字数」の2つの引数を含む関数 -- 例えば TextOut 等を呼び出すコードを描いてみるわけですよ。 すると……



int func()
{
    typedef std::basic_string<TCHAR> tstring;
    const tstring str = _T("ズルして楽していただきかしらーーー!?");

    // ↓warning C4267: 'size_t' から 'int' に変換しました。
    ::TextOut(hDC, 0, 0, str.c_str(), str.length() * sizeof(TCHAR));

    return 0;
}

basic_string::length() の戻り値が size_t なので、TextOut の第5引数 int cbString へ直接値を渡そうとすると、VS2003では*1警告が出てしまいます。 size_t は 64bit 環境では 64bit 幅になるので、int に直接投げると値が切り捨てられてしまう為にこんな警告が出てしまうわけです…


…が、どうにかならんかなぁー。^^;


#pragma で警告をOffにすると、本当にヤヴァイところが検出できなくなるので危険。
…かといって単純にキャストすると、64bit 環境の basic_string::length() で 0x00000001_00000000 見たいな値が返ってきた場合、下位32bitしか考慮されないので結構ヤヴァイ。*2

32bit でも 64bit でも 32bitの値しか取れない関数が悪いのか、int が 32bit 固定にしてしまった VCコンパイラが悪いのか、環境によってサイズが変わる size_t の戻り値が悪いのか……。



CAtlString等だと、APIがクラスにラッピングされているようなので、こんな問題に遭遇する事が少ない模様。こっちの方をメインに使う時期が来たのかしら〜? うむむむ…。

*1:VS2005の32bitコンパイラでも

*2:いやまぁ、こんな長い文字列なんざ扱う事はほぼ確実に無いでしょうけれど、一応可能性として…