次の古いC++コードをアップグレードして、最新のXcode 4.xコンパイラでコンパイルすると、元の開発者が機能するプログラミングイディオムを使用していたことがわかりましたが、回避する必要がありました。これはエラーになります。
*((USHORT*) pvPixel)++ = uRG; // copy red & green (2 bytes)
意図した内容がわかります。unsignedshort(uRG)をvoidポインター(pvPixel)が指すアドレスにコピーしてから、適切なサイズ(上記の場合は2バイト)ずつインクリメントします。問題は、pvPixelをキャストすると、左辺値ではなく一時的な値になり、許可されなくなることです。
元の開発者は、このイディオムを数十の場所で使用していました。これは、短時間で書き直すことができました。ただし、発生するたびにブルートフォースで書き直すのではなく、エレガントで読みやすいソリューションを提供することをお勧めします。マクロ、インライン関数、おそらくテンプレートなど、各オカレンスをブルートフォースで書き直すためのいくつかの可能な代替案を考えることができます。
私の質問は:この問題に対するC ++構文/言語の解決策はありますか?将来の開発者にとって最も明確なコードを生み出すアプローチは何でしょうか?
(以下の2つの関数例):
void PrimSurfaceGDI3::mFillHLine( UINT uRGB, UINT uX, UINT uY, UINT uW )
{
LPVOID pvPixel;
if ( uW > 0 )
{
// obtain a pointer to a specified pixel in the surface
pvPixel = mPtr( uX, uY );
USHORT uRG = *(USHORT*) &uRGB;
BYTE uB = ((BYTE*) &uRGB)[2];
LPVOID pvEnd = (BYTE*) pvPixel + uW * 3;
while (pvPixel < pvEnd)
{
// The two lines below are now ILLEGAL in modern compilers because casting pvPixel to USHORT* or BYTE* results in a TEMPORARY, not an lvalue
*((USHORT*) pvPixel)++ = uRG; // copy red & green (2 bytes)
*((BYTE*) pvPixel)++ = uB; // copy blue (1 byte)
}
}
}
以下では、このイディオムはforループの再初期化ステートメントで使用されます。
void PrimSurfaceGDI3::mFillVLine( UINT uRGB, UINT uX, UINT uY, UINT uH )
{
LPVOID pvPixel = mPtr( uX, uY );
USHORT uRG = *(USHORT*) &uRGB;
BYTE uB = ((BYTE*) &uRGB)[2];
LPVOID pvEnd = (BYTE*) pvPixel + uH * muScan;
// The reinitialization statement is now ILLEGAL in modern compilers because casting pvPixel to BYTE* results in a TEMPORARY, not an lvalue
for ( ; pvPixel < pvEnd; ((BYTE*) pvPixel) += muScan)
{
*(USHORT*) pvPixel = uRG; // copy red & green (2 bytes)
((BYTE*) pvPixel)[2] = uB; // copy blue (1 byte)
}
}