Chiharu の日記

絵描き C/C++ プログラマーの日記です。

C++0x 〜auto に対する不満

以前の日記にも書きましたが、C++0x のauto は便利です。左辺値の型推論とでも言うんでしょうか。

// C++0x より前
std::vector<int>::iterator aIt = aVec.begin();

と書いていたものが、

// C++0x
auto aIt = aVec.begin();

で済むようになる。と。
これはすごく便利で、パラレル・フォースでは、上記のように左辺値の型を明示しない書き方でコードの大半が構成されています。
んー。で、タイトルにある不満ですが…。
RISC CPU の場合*1、整数演算の際、整数レジスタ長未満の型の計算で、C/C++ コンパイラが計算結果のビット長を合わせるために、演算処理の都度マスク処理を挿入してくれる、という素敵仕様があります。マスク処理が挿入されれば、当然オーバーヘッドが発生します。
これを回避する方法としては、演算対象が std::uint16_t だったとして、演算中は std::uint_fast16_t として計算して、演算後に std::uint16_t に戻す、というのが妥当です。

const std::uint16_t foo(const sd::uint16_t iVal)
{
 std::uint_fast16_t aVal = iVal;
 // aVal に対していろいろ計算
 return aVal;
}

上記のように本来の型名がコードの近くに存在する状況であればまだ書けるのですが、そうでない場合は、型の選択に手間が掛かります。

struct Image {
 const std::uint16_t getWidth() const;
};
const std::uint16_t foo(const Image& iImage)
{
 std::uint_fast16_t aVal = iImage.getWidth();
 // aVal に対していろいろ計算
 return aVal;
}

私、上記のケースで std::uint_fast16_t をさっと導き出せる自信がありません。下記のように書けたら最高なんですけれど、そういう機能は C++0x にはないのかな。

auto_fast aVal = iImage.getWidth(); // auto_fast = std::uint_fast16_t

*1:Intel CPU では異なるビット長の整数レジスタを持っているのであまり気にしなくてもよさそうですが